Это дополнительный ответ, чтобы помочь объяснить карты и сгибы. Для приведенных ниже примеров я буду использовать этот список. Помните, этот список неизменен, поэтому он никогда не изменится:
var numbers = [1, 2, 3, 4, 5]
Я буду использовать числа в моих примерах, потому что они приводят к легкому для чтения коду. Помните, однако, что сгибы можно использовать для всего, для чего может быть использован традиционный императивный цикл.
Карта принимает список чего - либо, и функцию, и возвращает список , который был модифицирован с помощью функции. Каждый элемент передается в функцию и становится тем, что возвращает функция.
Самый простой пример этого - просто добавление номера к каждому номеру в списке. Я буду использовать псевдокод, чтобы сделать его независимым от языка:
function add-two(n):
return n + 2
var numbers2 =
map(add-two, numbers)
Если вы печатаете numbers2
, вы увидите, [3, 4, 5, 6, 7]
какой из них является первым списком с 2, добавленными к каждому элементу. Обратите внимание, что функция add-two
была дана map
для использования.
Fold s похожи, за исключением того, что функция, которую вы должны дать им, должна принимать 2 аргумента. Первым аргументом обычно является аккумулятор (в левом сгибе, которые являются наиболее распространенными). Аккумулятор - это данные, которые передаются во время цикла. Второй аргумент - это текущий элемент списка; так же, как выше для map
функции.
function add-together(n1, n2):
return n1 + n2
var sum =
fold(add-together, 0, numbers)
Если вы напечатаете, sum
вы увидите сумму списка чисел: 15.
Вот какие аргументы нужно fold
сделать:
Это функция, которую мы даем фолду. Сгиб будет передавать функцию текущего аккумулятора и текущий элемент списка. Все, что возвращает функция, станет новым аккумулятором, который будет передан функции в следующий раз. Это то, как вы «запоминаете» значения при зацикливании в стиле FP. Я дал ему функцию, которая берет 2 числа и добавляет их.
Это начальный аккумулятор; то, что аккумулятор запускается, как и прежде, чем любые элементы в списке обрабатываются. Когда вы суммируете числа, какова общая сумма до того, как вы сложили все числа вместе? 0, который я передал в качестве второго аргумента.
Наконец, как и в случае с картой, мы также передаем список чисел для обработки.
Если сгибы все еще не имеют смысла, подумайте об этом. Когда вы пишете:
# Notice I passed the plus operator directly this time,
# instead of wrapping it in another function.
fold(+, 0, numbers)
Вы в основном помещаете переданную функцию между каждым элементом в списке и добавляете начальный аккумулятор в левую или правую сторону (в зависимости от того, сложен ли он влево или вправо), поэтому:
[1, 2, 3, 4, 5]
становится:
0 + 1 + 2 + 3 + 4 + 5
^ Note the initial accumulator being added onto the left (for a left fold).
Который равен 15.
Используйте, map
когда вы хотите превратить один список в другой список, такой же длины.
Используйте, fold
когда вы хотите превратить список в одно значение, например суммирование списка чисел.
Как отметил @Jorg в комментариях, «одно значение» не обязательно должно быть чем-то простым, например числом; это может быть любой отдельный объект, включая список или кортеж! То, как у меня на самом деле были клики, было для меня определить карту в терминах сгиба. Обратите внимание, как аккумулятор представляет собой список:
function map(f, list):
fold(
function(xs, x): # xs is the list that has been processed so far
xs.add( f(x) ) # Add returns the list instead of mutating it
, [] # Before any of the list has been processed, we have an empty list
, list)
Честно говоря, как только вы поймете каждое из них, вы поймете, что почти любой цикл можно заменить на фолд или карту.