【发布时间】:2015-11-06 07:33:46
【问题描述】:
有了新的 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] 的命名。
我认为这就像在 reduce 函数中一样,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)
每个项目都重复了,因为我在 println 语句中调用了 xf。
为什么它将每个项目重复两次?
为什么我是零?
进行推理时我总是会得到 nil 吗?
我可以转述这种行为吗?
反正我是这样做的
> (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) 我可以使用传感器创建实际的惰性序列吗?
【问题讨论】:
-
1) clojure.org/transducers - "传感器 xf 是一个转换堆栈...";所以,xf 是一个转换器(或 xfs 的组合),它不是一个函数 (f),所以将它命名为
xf -
1) 编辑:应该将其表述为'并将其与常规函数区分开来(f)将其命名为
xf' -
你在这里有非常有趣的问题,但我认为如果你从中提取更小的问题,你会得到更多更好的答案。问“1”可以是一个单独的问题(“xf 或 xform 在转换器上下文中的含义是什么?”),它甚至不需要示例,同样适用于问题 4 和 6。
标签: clojure transducer