Clojure的喜悦:“休息与下一个”样本在我的REPL中不会产生相同的结果

时间:2016-01-29 11:00:50

标签: clojure

以下摘录自“Clojure的喜悦”:

  

使用时创建可能无限的整数序列会发生什么   迭代,每次生成新值时打印一个点,然后使用其中任何一个   休息或旁边返回序列的前三个值?和...之间的不同   在下面的例子中可以看到rest和next:

     

(def非常懒惰( - >(迭代#(do(print。)(inc%))1)   休息休息))   ; => ..#'用户/非常-懒惰

     

(def less-lazy( - >(迭代#(do(print。)(inc%))1)   下一个下一个)))   ; => ...#“用户/不太懒惰

     

如图所示,下一个版本打印三个点,而其余版本仅打印   二。当从另一个构建一个懒的seq时,rest不会导致计算   (或实现)任何超出其需要的元素;接下来呢。为了确定   seq是否为空,接下来需要检查是否至少有一件事   它,因此可能导致一个额外的实现。这是一个例子:

     

(println(first very-lazy)); 0.4

     

(println(first less-lazy)); 4

以下是我在“Cursive IDE”REPL中的内容:

(def very-lazy (-> (iterate #(do (print \.) (inc %)) 1)
               rest rest rest))
..=> #'user/very-lazy
(def less-lazy (-> (iterate #(do (print \.) (inc %)) 1)
               next next next))
..=> #'user/less-lazy
(println (first very-lazy)) ; .4
.4
=> nil
(println (first less-lazy)) ; 4
.4
=> nil

我想我确实理解了不同行为的解释,但为什么输出在我的REPL中是相同的?

1 个答案:

答案 0 :(得分:6)

Clojure 1.7.0中iterate的实现发生了变化。在1.7之前,它是以conslazy-seq的形式实现的,它展示了你引用的JoC片段中描述的行为。从1.7开始,它是以专用的clojure.lang.Iterate类实现的,它以相同的方式处理restnext,因此它的行为与您在REPL中发现的一样。