【发布时间】:2015-10-08 18:49:41
【问题描述】:
我有这个功能,它似乎在有限的集合上工作得很好,但在无限的集合上却不行。有没有办法在其中构造一个 lazy-seq 以使其与无限 coll 一起运行,例如:(take 3 (m inc (range))) => (1 2 3)?
(defn m [f c] (reduce #(conj % (f %2)) [] c))
【问题讨论】:
我有这个功能,它似乎在有限的集合上工作得很好,但在无限的集合上却不行。有没有办法在其中构造一个 lazy-seq 以使其与无限 coll 一起运行,例如:(take 3 (m inc (range))) => (1 2 3)?
(defn m [f c] (reduce #(conj % (f %2)) [] c))
【问题讨论】:
这似乎是map 的一个用例
(map f c)
或者(当它必须是一个向量时)
(mapv f c)
编辑: 地图的可能重新实现:
(defn new-map [f coll]
(if (seq coll)
(lazy-seq
(cons (f (first coll))
(new-map f (rest coll))))))
【讨论】:
map
lazy-seq,例如我的示例?类似:(defn m [f c] (lazy-seq (reduce #(conj % (f %2)) [] c)))
reduce来偷懒。当您将 thing 的某些内容“放入”惰性序列中时,thing 将不会变得惰性!它将保持不变。使用lazy-seq 得到的懒惰如下:序列中的thing 只会在你到达/查看序列中的thing 时被评估。您的函数m 的结果与(mapv f c) 完全相同
reduce 将继续从序列中获取元素,直到返回 nil。因此,reduce 永远不会返回无限序列。
正如cmets中所指出的,reduced可以用来强制终止reduce,谢谢!
【讨论】:
reduced 来终止无限序列。
reduce 放入if 表达式中?