【问题标题】:Looping over vectors循环遍历向量
【发布时间】:2012-01-22 03:01:32
【问题描述】:

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

(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?

【问题讨论】:

  • 使用 (doseq [x myVec] (println x))

标签: vector map clojure list-comprehension


【解决方案1】:

formap 创建一个新的惰性序列,将原始向量中的每个元素替换为 (println element) 的结果,println 返回 nil。

您不应使用formap 对元素执行副作用(如打印)。为此使用doseq

【讨论】:

  • 有点混乱来自数据打印出来的顺序。初始括号被打印为 (map (println...)) 返回的列表的一部分,然后您获得每个 println 的输出,然后是 (map (println ...)) 列表中的 nil .如果您切换到使用doseq,或者如果您使用(doall (map (println ...))),结果将不那么模糊,因为您将在获得返回值之前看到所有打印。 (dorun (map (println ...))) 将返回。除非我得到了 dorun 和 doall 反转。
  • @SavanniD'Gerinel 你所说的有些模糊,但在大多数细节上都是错误的。事情以“错误”的顺序出现,因为序列是分块的,而不是因为 repl 在值之前打印副作用:如果您有一个像 (take 10 (iterate #(inc (doto % println)) 0)) 这样的未分块序列,您会看到返回值与打印结果交错。同样,如果您有一个大于单个块的列表(例如,大小为 50),您会得到一堆打印,然后是一堆值,然后是更多打印...
  • 内容丰富。我所说的要点是,您无法真正预测打印的顺序,但考虑到您在此处提到的分块,即使这样也是不准确的。就目前而言,我几天前才意识到分块。
【解决方案2】:

那些nilprintln 的返回值。每次打电话

(println "something")

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

【讨论】:

    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 2012-09-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-26
      • 2015-05-21
      • 1970-01-01
      • 2014-03-26
      • 1970-01-01
      相关资源
      最近更新 更多