С новым clojure 1.7 я решил понять, где я могу использовать преобразователи. Я понимаю, какую пользу они могут дать, но я не могу найти нормальные примеры написания пользовательских преобразователей с объяснением.
Хорошо, я пытался проверить, что происходит. Я открыл документацию clojure. И там примеры используют xf
как аргумент. Во-первых: что означает этот xf или xfrom?
Этот материал создал преобразователь идентификации.
(defn my-identity [xf]
(fn
([]
(println "Arity 0.")
(xf))
([result]
(println "Arity 1: " result " = " (xf result))
(xf result))
([result input]
(println "Arity 2: " result input " = " (xf result input))
(xf result input))))
Я взял именование переменных [result input]
из примера документации.
Я думал, что это как функция уменьшения, где result
- сокращенная часть, а input
- новый элемент коллекции.
Итак, когда я делаю (transduce my-identity + (range 5))
, я получил результат 10
, которого я ожидал.
Затем я прочитал о eduction
, но я не могу понять, что это такое. Так или иначе
Я сделал (eduction my-identity (range 5))
и получил:
Arity 2: nil 0 = nil
Arity 2: nil 1 = nil
Arity 1: nil = nil
(0 0 1 1)
Каждый элемент получил дублирование, потому что я вызываю xf
в println
.
Почему он дублировал каждый пункт дважды?
Почему я получил нуль?
Будут ли я всегда получать ноль, делая урок?
Могу ли я передать это поведение?
В любом случае я сделал
> (reduce + (eduction my-identity (range 5))
clojure.core.Eduction cannot be cast to clojure.lang.IReduce
Хорошо, результатом является eduction
, который НЕ выводится, но печатается как список. Почему это не приводимо? Когда я набираю (doc eduction)
, я получаю, что
Returns a reducible/iterable application of the transducers
to the items in coll.
Не должны ли теги (transduce xform f coll)
и (reduce f (eduction xfrom coll))
?
Я сделал
> (reduce + (sequence my-identity (range 5))
20
Конечно, я получил 20
из-за дубликатов. Снова я подумал, что это должно быть
что (transduce xform f coll)
и (reduce f (sequence xfrom coll))
be
всегда равны по крайней мере в таком маленьком примере без каких-либо преобразователей состояния. Это глупо, что это не так, или я ошибаюсь?
Хорошо, тогда я попробовал (type (sequence my-identity (range 5)))
и получил clojure.lang.LazySeq
Я думал, что он ленив, но когда я попытался взять элемент first
clojure вычислил всю последовательность сразу.
Итак, мое резюме:
1) Что означает xf или xform?
2) Почему я получаю nil
как аргумент result
, а eduction
или sequence
?
3) Могу ли я всегда быть уверенным, что он будет nil
, а eduction
или sequence
?
4) Что такое eduction
, а какая идиоматическая идея не сводится? Или, если это так, то как я могу уменьшить его?
5) Почему я получаю побочные эффекты, когда sequence
или eduction
?
6) Могу ли я создать фактические ленивые последовательности с преобразователями?