Я узнал основную разницу между foldLeft
иreduceLeft
foldLeft:
- начальное значение должно быть передано
reduceLeft:
- принимает первый элемент коллекции в качестве начального значения
- выдает исключение, если коллекция пуста
Есть ли другая разница?
Есть какая-то конкретная причина иметь два метода с похожей функциональностью?
scala
functional-programming
fold
higher-order-functions
Раджеш Питти
источник
источник
Ответы:
Несколько вещей, чтобы упомянуть здесь, прежде чем дать фактический ответ:
left
, а скорее о разнице между уменьшением и сворачиваниемВернуться к вашему вопросу:
Вот подпись
foldLeft
(также могла бы послужитьfoldRight
причиной, которую я собираюсь изложить):А вот и подпись
reduceLeft
(опять же направление здесь не имеет значения)Эти два выглядят очень похожими и, таким образом, вызвали путаницу.
reduceLeft
это особый случайfoldLeft
(что, кстати, означает, что иногда вы можете выразить одно и то же, используя любой из них).Когда вы вызываете
reduceLeft
say для a,List[Int]
это буквально сократит весь список целых чисел до единого значения, которое будет иметь типInt
(илиInt
, следовательно, супертип[B >: A]
).Когда вы вызываете
foldLeft
say для a,List[Int]
он свернет весь список (представьте, что вы катите лист бумаги) в одно значение, но это значение не обязательно должно даже быть связано сInt
(следовательно[B]
).Вот пример:
Этот метод принимает
List[Int]
и возвращаетTuple2[List[Int], Int]
или(List[Int], Int)
. Он вычисляет сумму и возвращает кортеж со списком целых чисел и его суммой. Кстати, список возвращается в обратном порядке, потому что мы использовалиfoldLeft
вместоfoldRight
.Смотрите One Fold, чтобы править ими все для более глубокого объяснения.
источник
B
это супертипA
? Похоже, наB
самом деле должен быть подтипA
, а не супертип. Например, если предположитьBanana <: Fruit <: Food
, что если бы у нас был списокFruit
s, кажется, что он может содержать некоторыеBanana
s, но если бы он содержал какие-либоFood
s, то тип был быFood
, правильно? Таким образом, в этом случае, еслиB
есть супертипA
и существует список, содержащий какB
s, так иA
s, список должен иметь типB
, а неA
. Можете ли вы объяснить это несоответствие?List[Banana]
может быть уменьшена до одного,Banana
одногоFruit
или одногоFood
. Потому чтоFruit :> Banana
и "Еда:> Банан".Banana
может содержатьFruit
», что не имеет смысла. Ваше объяснение имеет смысл -f
передаваемая функцияreduce()
может привести к aFruit
или aFood
, что означает, чтоB
в сигнатуре должен быть суперкласс, а не подкласс.reduceLeft
это просто удобный метод. Это эквивалентноисточник
reducelft
хотяfold
работает в пустом списке, в то времяreduce
как нет.foldLeft
является более общим, вы можете использовать его для создания чего-то совершенно отличного от того, что вы изначально вставили. Принимая во внимание, чтоreduceLeft
можно получить только конечный результат того же типа или супертипа типа коллекции. Например:foldLeft
Применят закрытия с последним сложенным результатом (первый раз , используя начальное значение) и следующее значение.reduceLeft
с другой стороны, сначала объединят два значения из списка и применят их к закрытию. Далее он объединит остальные значения с совокупным результатом. Видеть:Если список пуст,
foldLeft
можно представить начальное значение как законный результат.reduceLeft
с другой стороны, не имеет допустимого значения, если не может найти хотя бы одно значение в списке.источник
Основная причина, по которой они оба находятся в стандартной библиотеке Scala, вероятно, заключается в том, что они оба находятся в стандартной библиотеке Haskell (называемой
foldl
иfoldl1
). Если быreduceLeft
не было, его бы очень часто определяли как удобный метод в разных проектах.источник
Для справки,
reduceLeft
произойдет ошибка при применении к пустому контейнеру со следующей ошибкой.Переработка кода для использования
это один из возможных вариантов. Другой
reduceLeftOption
вариант - использовать вариант, который возвращает результат в варианте.источник
Из Принципов функционального программирования в Scala (Мартин Одерский):
[в отличие от
reduceLeft
, который вызывает исключение при вызове в пустом списке.]Курс (см. Лекцию 5.5) предоставляет абстрактные определения этих функций, которые иллюстрируют их различия, хотя они очень похожи в использовании сопоставления с образцом и рекурсии.
Обратите внимание, что
foldLeft
возвращается значение типаU
, которое не обязательно совпадает с типомList[T]
, но reduLeft возвращает значение того же типа, что и список).источник
Чтобы действительно понять, что вы делаете со сложением / уменьшением, проверьте это: http://wiki.tcl.tk/17983 очень хорошее объяснение. как только вы поймете концепцию сгиба, сокращение придет вместе с ответом выше: list.tail.foldLeft (list.head) (_)
источник