Я предполагаю, что вы говорите о clojure.core.reducers / fold .
Scala по умолчанию fold
реализация последовательностей очень проста:
collection.fold(identityElem)(binOp)
просто начинается с identityElem
, затем последовательно проходит сбор и применяет двоичную операцию binOp
к уже накопленному результату и текущему значению последовательности, например,
(1 to 3).fold(42000)(_ + _)
приведет к 42000 + 1 + 2 + 3
= 42006
.
Clojure's fold
с полной подписью
(r/fold n combinef reducef coll)
из вышеупомянутого пакета работает параллельно в два этапа. Сначала он разбивает входные данные на более мелкие группы размером n
(приблизительно), затем сокращает каждую группу, используя reducef
, и, наконец, объединяет результаты каждой группы, используя combinef
.
Основное отличие состоит в том, что combinef
, как ожидается, будет одновременно нулевым и бинарным одновременно (Clojure имеет многозадачные функции), и будет вызываться (combinef)
(без аргументов) для создания элементов идентификации для каждого раздела (таким образом, эта документация является правильной, а эта документация лежит).
То есть, чтобы смоделировать сгиб Скалы из приведенного выше примера, нужно написать что-то вроде этого:
(require '[clojure.core.reducers :as r])
(r/fold 3 (fn ([] 42000) ([x y] y)) + [1 2 3])
И вообще у Скалы fold
collection.fold(identityElement)(binOp)
можно эмулировать с помощью reducers/fold
следующим образом:
(r/fold collectionSize (fn ([] identityElem) ([x y] y)) binOp collection)
(обратите внимание на хитрое ([x y] y)
, которое отбрасывает первый аргумент, оно намеренно).
Полагаю, интерфейс не был предназначен для использования с любыми нулевыми двоичными операциями, которые не являются моноидами, поэтому Scala fold
так неудобно моделировать с использованием Clojure fold
. Если вы хотите что-то, что ведет себя как fold
Scala, используйте reduce
в Clojure.
EDIT
Ой, подожди. Документация фактически заявляет, что
объединение должно быть ассоциативным, и, когда вызывается без
arguments, (combf) должен создать свой элемент идентичности
то есть мы на самом деле вынуждены использовать моноид в качестве combinef
, поэтому приведенный выше пример 42000, ([x y] y)
на самом деле недопустим, а поведение фактически не определено. Тот факт, что я каким-то образом получил 42006
, был хаком в строго техническом смысле, поскольку для получения желаемого результата он полагался на неопределенное поведение библиотечной функции 42006
.
Принимая во внимание эту дополнительную информацию, я не уверен, что Scala fold
может быть имитирован Clojure core.reducers/fold
вообще. fold
Clojure, кажется, ограничен сокращениями с моноидом, тогда как сгиб Скалы ближе к общему List
катаморфизму за счет параллелизма.