Clojure 延迟序列的实现时序

Clojure 延迟序列的实现时序,clojure,lazy-sequences,Clojure,Lazy Sequences,为什么是输出 (defn square [x] (do (println (str "Processing: " x)) (* x x))) (println (map square '(1 2 3 4 5))) 不是 因为map是懒惰的。它在封面下使用了lazy seq,它可以。因此,当代码获取map序列的第一个值时,会出现两个println语句 另请参阅此博客帖子:println在其内部使用[[x&xs]xs]解构表单。这相当于[x(第一个xs),xs(下一个xs)]

为什么是输出

(defn square [x]
  (do
    (println (str "Processing: " x))
    (* x x)))

(println (map square '(1 2 3 4 5)))
不是


因为
map
是懒惰的。它在封面下使用了lazy seq,它可以。因此,当代码获取
map
序列的第一个值时,会出现两个
println
语句


另请参阅此博客帖子:

println
在其内部使用
[[x&xs]xs]
解构表单。这相当于
[x(第一个xs),xs(下一个xs)]
,因此它在打印第一个项目之前实现了这两个项目

比如说,

(Processing: 1
1 Processing: 2
4 Processing: 3 
9 Processing: 4 
16 Processing: 5 
25)

你喜欢我用代码片段学习吗?这里有一些

让我们看看
map
的文档

=> (defn fn1 [[x & xs]] nil)
#'user/fn1
=> (fn1 (map square '(1 2 3 4 5)))
Processing: 1
Processing: 2
nil
map
返回一个延迟序列(您应该已经阅读了@noahz给出的引用)。要完全实现延迟序列(这通常不是一个好的实践,因为延迟序列可能是无限的,因此永远不会结束),您可以使用
dorun
doall

user=> (doc map)
-------------------------
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])
  Returns a lazy sequence consisting of the result of applying f to the
  set of first items of each coll, followed by applying f to the set
  of second items in each coll, until any one of the colls is
  exhausted.  Any remaining items in other colls are ignored. Function
  f should accept number-of-colls arguments.
nil
user=> (doc dorun)
-------------------------
clojure.core/dorun
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. dorun can
  be used to force any effects. Walks through the successive nexts of
  the seq, does not retain the head and returns nil.
nil
user=> (doc doall)
-------------------------
clojure.core/doall
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. doall can
  be used to force any effects. Walks through the successive nexts of
  the seq, retains the head and returns it, thus causing the entire
  seq to reside in memory at one time.
nil
尽管它们看起来很相似,但它们并不介意它们对待已实现序列的头部的不同

有了这些知识,您可以使用
doall
影响映射惰性序列的行为方式

user=> (doc map)
-------------------------
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])
  Returns a lazy sequence consisting of the result of applying f to the
  set of first items of each coll, followed by applying f to the set
  of second items in each coll, until any one of the colls is
  exhausted.  Any remaining items in other colls are ignored. Function
  f should accept number-of-colls arguments.
nil
user=> (doc dorun)
-------------------------
clojure.core/dorun
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. dorun can
  be used to force any effects. Walks through the successive nexts of
  the seq, does not retain the head and returns nil.
nil
user=> (doc doall)
-------------------------
clojure.core/doall
([coll] [n coll])
  When lazy sequences are produced via functions that have side
  effects, any effects other than those needed to produce the first
  element in the seq do not occur until the seq is consumed. doall can
  be used to force any effects. Walks through the successive nexts of
  the seq, retains the head and returns it, thus causing the entire
  seq to reside in memory at one time.
nil
正如您可能已经注意到的那样,我还更改了
square
函数的定义,因为您不需要
do
在函数中(它与
defn
宏是隐式的)

在这本书中,有一句话你可能喜欢用在
”(12345)

“大多数人只是在这种情况下使用向量文字,其中包含成员表达式 将始终进行评估。”


与其复制相关章节来支持这一说法,我宁愿推荐这本书,因为它值得花时间和金钱。

lazy seq不会预缓存
rest
的结果。你链接到的这篇文章是一篇多年前的文章,描述了一些从未应用过的正在进行的工作,试图解决一个不再存在的问题。爱丽丝的解释是正确的。编辑好的,这项工作确实得到了应用,但我不明白你是如何得到这样的印象的:有任何预缓存正在进行中-如果有,懒惰的seq将不会是懒惰的,因为他们将递归地“预缓存”整个懒惰序列!好吧,我误用了“预缓存”这个词,这篇博文进一步误导了我。我的意思是“在打印前评估前两个元素。”