问题 循环向量


我是Clojure的新手并且发现当我使用列表理解在clojure中循环这个向量时,我得到了一些 nil在最后。

(def myVec [1,2,3])

user=> (for [x myVec] (println x))
(1
2
3
nil nil nil)

我用同样的东西 map

user=> (map println myVec)
(1
2
3
nil nil nil)

是什么原因导致在这些情况下打印nill?


11377
2017-12-16 15:52


起源

使用(doseq [x myVec](println x)) - BLUEPIXY


答案:


那些 nil 是的回报值 println。每次打电话

(println "something")

println 功能打印 something 在标准输出上,然后返回 nil。代码中的整体效果是您可以看到所有副作用(I / O) println 调用,然后REPL打印来自每次调用的返回值(例如三次 nil)。


6
2017-12-16 15:57





for 和 map 创建一个新的延迟序列,原始向量中的每个元素都替换为(println element),和 println 返回零。

你不应该使用 for 和 map 对元素执行副作用(如打印)。使用 doseq 为了那个原因。


9
2017-12-16 15:56



一些混乱来自数据打印的顺序。初始括号被打印为列表的一部分(map(println ...))返回,然后你得到每个println的输出,然后是nils(map(println ...))列表的一部分。如果您切换到使用doseq,或者如果您(doall(map(println ...))),结果将不那么模糊,因为在获得返回值之前您将看到所有打印。 (dorun(地图(println ...)))将返回。除非我得到了休伦并且全部逆转了。 - Savanni D'Gerinel
@ SavanniD'Gerinel你所说的东西含糊不清,但在大多数细节上都是错误的。事情以“错误”的顺序出现,因为序列被分块,而不是因为repl在值之前打印副作用:如果你有一个像unocunked序列那样的 (take 10 (iterate #(inc (doto % println)) 0)),您会看到与打印结果交错的返回值。同样地,如果你的列表大于单个块(比如大小为50),你会获得一堆打印,然后是一堆值,然后是更多的打印...... - amalloy
这是有益的。我所说的要点是你无法真实地预测打印事物的顺序,但即使这样也不准确,因为你在这里指的是分块。就目前而言,我几天前才意识到分块。 - Savanni D'Gerinel


nil 是println返回的值,因此您看到打印的行后面是nil值的映射列表。


1
2017-12-16 15:56