Clojure преобразователи поведения
С новым 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))
быть всегда равным, по крайней мере, в таком маленьком примере без каких-либо датчиков состояния. Это глупо, что их нет, или я не прав?
Хорошо, тогда я попробовал(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) Могу ли я создать настоящие ленивые последовательности с преобразователями?