Kan*_*thy 3 clojure lazy-evaluation
我正在学习clojure.在解决其中一个问题时,我不得不使用first
+ filter
.我注意到过滤器对所有输入都不必要地运行.如何让filter
懒惰运行,以便它不需要为整个输入应用谓词.
以下是一个显示它不是懒惰的例子,
(defn filter-even
[n]
(println n)
(= (mod n 2) 0))
(first (filter filter-even (range 1 4)))
Run Code Online (Sandbox Code Playgroud)
上面的代码打印出来
1
2
3
而它不需要超越2
.我们怎么能让它变得懒惰?
这range
是因为是一个分块序列:
(chunked-seq? (range 1))
=> true
Run Code Online (Sandbox Code Playgroud)
如果可用,它实际上将采用前32个元素:
(first (filter filter-even (range 1 100)))
1
2
. . .
30
31
32
=> 2
Run Code Online (Sandbox Code Playgroud)
此概述显示了unchunk
防止这种情况发生的功能.不幸的是,它不是标准的:
(defn unchunk [s]
(when (seq s)
(lazy-seq
(cons (first s)
(unchunk (next s))))))
(first (filter filter-even (unchunk (range 1 100))))
2
=> 2
Run Code Online (Sandbox Code Playgroud)
或者,您可以申请list
,因为列表没有分块:
(first (filter filter-even (apply list (range 1 100))))
2
=> 2
Run Code Online (Sandbox Code Playgroud)
但显然,整个系列需要实现预过滤.
老实说,这并不是我曾经过于关注的事情.过滤功能通常不是太昂贵,并且在宏观方案中32个元素块并不是那么大.