为什么for函数没有执行

Why the for function is not executed

我是clojure初学者,有一个困惑的问题:

(do (println "ok") (for [x [1 2 3]] (println x)))

输出: 行 1个 2个 3

这个我能理解,但是


(do (for [x [1 2 3]] (println x)) (println "ok"))

输出: 行 无

为什么for函数没有执行?

简而言之:do 宏计算所有参数,return 是最后一个参数的值,这迫使惰性序列的元素实现。

我假设您在 REPL 中评估了两个表达式。

由于 for 宏,第一个表达式 return 是惰性序列。 REPL 强制计算 returned 值(因此它可以显示计算结果)因此序列的每个元素都通过打印到屏幕的副作用来实现。

在第二种情况下,return 值为 nil,因为 do form was a println 调用中的最后一个表达式。在这种情况下也创建了惰性序列,但它的元素从未实现,因为从未使用过该值。

如果你想强制计算一个序列,你可以使用doalldorun。如果你对序列不感兴趣,只需要一个循环结构,你可以使用 doseq 而不是 for.

您示例中的 (println x) 形式是 side-effects,只有实现 for 惰性序列才会出现。

这是重新格式化的第一个示例:

(do
  (println "ok")
  (for [x [1 2 3]]
    (println x)))

do 依次计算表达式,returns 最后一个的值。这里的最后一个表达式是一个惰性序列。如果您在 REPL 中评估它,惰性序列将实现打印其元素(给出值 (nil nil nil))并导致 side-effects 打印 1 2 3.

这是重新格式化的第二个例子:

(do
  (for [x [1 2 3]]
    (println x))
  (println "ok"))

再次do依次计算表达式。第一个是惰性序列,但它的值未被使用,因此从未实现。这意味着打印 1 2 3 的 side-effects 不会发生。

其他答案已经给出了很好的背景。如果您需要 for 的高级功能但不想要懒惰的方面,只需将整个内容包装在 (vec ...) 形式中:

(vec (for [x [1 2 3]]
       (println x)))

这已经在 forv 宏中为您完成,可以 be seen here