【问题标题】:repeatedly vs. binding反复与绑定
【发布时间】:2018-01-25 03:02:45
【问题描述】:
(def ^:dynamic *d* 1)

(binding [*d* 2]
  (println *d*)
  (repeatedly 1 #(println *d*)))

输出:

2
1

为什么?为什么repeatedly里面的函数会从binding外面看到动态var的值?

顺便查了一下(.getId (java.lang.Thread/currentThread))匿名函数内外:是一样的。

【问题讨论】:

    标签: clojure thread-safety lazy-evaluation


    【解决方案1】:

    repeatedly 创建的惰性序列从表单返回,然后只有在通过 REPL 打印时才实现,在绑定已“展开”之后,此时正在调用匿名函数。要查看是否是这种情况,请尝试以下两种变体:

    (binding [*d* 2]
      (println *d*)
      (let [x (repeatedly 1 #(println *d*))]
        (println (realized? x))
        x))
    

    (binding [*d* 2]
      (println *d*)
      (doall (repeatedly 1 #(println *d*))))
    

    第二个变体强制序列在绑定范围内完全实现。

    请注意,另一种解决问题的方法是使用bound-fn“捕获”绑定:

    (binding [*d* 2]
      (println *d*)
      (repeatedly 1 (bound-fn [] (println *d*)))) 
    

    【讨论】:

    • 就是这样。哎哟!这是一个容易犯的错误。感谢您的明确解释——感谢您将我指向 bound-fndoall
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多