在clojure的println!(按惰性顺序)

在clojure的println!(按惰性顺序),clojure,Clojure,1) (def x(用于[i(范围13)](do(println i)i))) 2) (def x(用于[i(范围13)](doi))) 两者都产生相同的输出,那么println的用途是什么?值自行计算,do块返回最后一个表达式的结果。这就是为什么(do2)在下面的示例中返回2。因为它返回2,当从REPL求值时,2将作为结果打印到屏幕上。 但是,函数println会产生副作用,但返回nil。下面的副作用是将值2打印为标准输出。还将打印nil,因为这是函数println的返回值 user=>

1)
(def x(用于[i(范围13)](do(println i)i)))

2)
(def x(用于[i(范围13)](doi)))


两者都产生相同的输出,那么println的用途是什么?

值自行计算,do块返回最后一个表达式的结果。这就是为什么(do2)在下面的示例中返回2。因为它返回2,当从REPL求值时,2将作为结果打印到屏幕上。 但是,函数println会产生副作用,但返回nil。下面的副作用是将值2打印为标准输出。还将打印nil,因为这是函数println的返回值

user=> (do 2)
2
user=> (println 2)
2
nil
在您的示例中,由于我上面解释的原因,输出是不一样的。你自己注意一下区别:

user=> (def x (for [i (range 1 3)] (do (println i) i)))
#'user/x
user=> x
(1
2
1 2)
user=> (def x (for [i (range 1 3)] (do i)))
#'user/x
user=> x
(1 2)
还要注意的是,for是懒惰的

(def x (for [i (range 1 3)] (do (println i) i)))
#'user/x
user=> x
(1
2
1 2)
user=> x
(1 2)

第二次请求x时,仅打印(12)。为什么?因为for是懒惰的。它仅在第一次请求元素时(第一次请求x时)生成其元素。下一次,元素已经生成,因此do中的副作用不会再次发生。

在REPL中,它们可能会生成(大致)相同的输出,但如果从编译程序运行,则不会。REPL中的P代表Print-它打印当前表达式的值


试着编译到一个Jar中并运行它,看看有什么不同。也不要忘记使用println意味着你的函数有副作用;您可能会发现需要强制对函数进行求值(例如在do中)才能生成输出。

但对于第一次执行后的println,它仅打印(12),只有第一次输出与我所说的懒惰不同。另请看:这是一个更好的答案,因为它实际上触及了问题的根源。