Clojure уменьшить преобразователь
Я ищу простой пример преобразователей с понижающей функцией. Я надеялся, что следующее вернет функцию преобразования, так как (filter odd?)
работает так:
(def sum (reduce +))
clojure.lang.ArityException: Wrong number of args (1) passed to: core$reduce
Мое текущее понимание преобразователей состоит в том, что, опуская аргумент коллекции, мы возвращаем функцию преобразования, которую мы можем составить с другими функциями преобразования. Почему это отличается для filter
а также reduce
?
1 ответ
reduce
функция не возвращает преобразователь. Это так из-за reduce
это функция, которая возвращает значение, которое может быть последовательностью Другая функция, как filter
или же map
всегда возвращает последовательности (даже пустые), что позволяет комбинировать эти функции.
Для объединения чего-либо с функцией Reduce, вы можете использовать библиотеку редуктора, которая дает функциональность, аналогичную той, что вы хотите сделать (если я правильно понял это).
UPD
Хорошо, мой ответ немного сбивает с толку. Прежде всего, давайте посмотрим, как filter
, map
и многие другие функции работают: неудивительно, что вся эта функция основана на reduce
, это функция сокращения (таким образом, они не создают коллекцию большего размера, чем входная). Таким образом, если вы каким-либо образом уменьшаете некоторый колл - вы можете объединить ваше сокращение, чтобы передать приводимое значение из сводимого колла между всеми функциями сокращения, чтобы получить конечное значение. Это отличный способ улучшить производительность, потому что, как мы надеемся, часть значений как-то будет равна нулю (как часть преобразования), и существует только один логический цикл (я имею в виду цикл, вы перебираете последовательность только один раз и пропускаете каждое значение через все преобразование). Итак, почему reduce
Функция настолько отличается, потому что все на ней построено?
Все traducer основано на простой и эффективной идее, которая, на мой взгляд, выглядит как сито. Но сокращение может быть только для последнего шага, потому что в результате только одно значение. Таким образом, единственный способ, которым вы можете использовать reduce
здесь, чтобы обеспечить coll
и форма сокращения. Аналогия уменьшения в сите похожа на воронку под ситом: вы берете свою коллекцию, бросаете ее в какую-то функцию, такую как map, filter и take - и, как вы можете видеть, размер новой коллекции, являющейся результатом преобразования, никогда не будет больше, чем в как входная коллекция. Таким образом, последний шаг может быть reduce
который принимает просеянную коллекцию и принимает одно значение на основе всего, что было сделано.
Существует также другая функция, которая позволяет комбинировать преобразователи и редукторы - transducer
, но это также требует функции, потому что это как точка входа и последний шаг в нашем сите.
Библиотека редукторов похожа на преобразователи и также позволяет reduce
как последний шаг. Это просто другой подход, чтобы сделать то же самое, что и преобразователь.
Для достижения того, что вы хотите сделать, вы можете использовать partial
функция вместо Было бы так:
(def sum
(partial reduce +'))
(sum [1 2 3])
вернет очевидный ответ 6