【问题标题】:why can't I call a println after a while in defn body in Clojure?为什么我不能在 Clojure 的 defn 正文中调用 println?
【发布时间】:2013-03-06 02:28:39
【问题描述】:

我有一个看起来像的函数,

(defn app [server]
  (println "before while...."))
  (while test
    while-body)
  (println "...after while."))

但是,当我调用 fn 时,我只在 REPL 中看到“之前的 while”,然后当 while 测试失败时,“nil”。

如果我在 repl 上写一个测试 foo,比如

(defn foo [] 
  (println "testing before")
  (loop [i 100]
    (when (> i 10)
      (prn i)
      (recur (- i 2))))
  (println "after..."))

它按我的预期工作。

如果有帮助,我已将实际代码粘贴到此处,https://www.refheap.com/paste/12147

什么解释了这里的行为差异?

编辑

很抱歉之前没有尝试过,但这确实适用于 REPL:

(defn bar []
  (let [i (atom 100)]
    (println "before...")
    (while (> @i 10)
      (swap! i dec))
    (println "after...")))

所以还有其他事情发生。

编辑#2

在 repl 上进行更多测试,如果我注释掉 while 循环,将打印之前和之后的 println。我之前对“nil”有误解,这是在调用 while 之后调用的另一个函数的返回值。所以它似乎与while循环有关。

我注意到如果我将 while 更改为此

(loop []
  (if test
    (do things and recur...)
    (println "test failed")))

“测试失败”永远不会打印到 repl。

【问题讨论】:

  • 是的,关于我正在打的未来电话,发生了一些有趣的事情......但是我只是检查了测试是否为假 while 终止之后,确实如此。
  • 您确定 while 循环实际上正在终止吗?我的另一个建议是在最终的 (println) 之后放置一个 (flush),因为它可能会在某处缓冲。
  • @Alex,谢谢你,你给了我需要的提示。问题隐藏在另一个函数中(一个没有超时的选择调用)。选择被阻塞,所以我的关闭功能没有正确清理。

标签: clojure


【解决方案1】:

在第一个 println 的末尾有一个多余的 )。

(defn app [server]
  (println "before while....")
  (while test
    while-body)
  (println "...after while."))

但由于这显然是您没有运行的示例代码,我预计问题出在您确实运行的代码中。如果这不能解决问题,请按原样复制并粘贴代码。

【讨论】:

    【解决方案2】:

    问题不是我想的那样。我阻塞了一个选择调用(在while循环中调用),这导致我的关闭函数出现问题,它结束了while循环。为选择添加超时修复它。

    【讨论】:

      【解决方案3】:

      在 Clojure 函数定义中,最后要评估的是返回的内容,并且 (println ...) 返回 nil

      【讨论】:

      • 为什么 println 本身不会将它的参数打印到 repl?
      猜你喜欢
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多