请在Clojure 2024调查问卷中分享您的想法!

欢迎!请参阅关于页面了解有关此信息的一些更多内容。

0
Clojure

这是已知的特性吗?愿意了解导致这种情况的原因。一种预感是,在字节码层面, recur 仅仅是一个循环/跳转,因此代码更改不会得到反映。

(defn x
  []
  (recur))

(future (x))

(defn x
  []
  (println "reloaded")
  (recur)) ;; changes in fn (print statement) after reloading x does not get reflected in the recur variant which is still executing

(defn y
  []
  (y))

(future (y))

(defn y
  []
  (println "reloaded")
  (y)) ;; changes get reflected now

2 答案

0

择优选择
 
最佳答案

clj-java-decompiler 对于函数 x 显示的基本上是这样

public static Object invokeStatic() {
    while (true) {}
}

对于 y 则是这样

public static final Var const__0;

public static Object invokeStatic() {
    return ((IFn)const__0.getRawRoot()).invoke();
}

这就是 recur 的用途,即优化尾递归。在某个时候, y 将耗尽栈空间,所以确实, recur 不能动态地重新绑定。

0

您可以使用变量来获得您希望的结果。

(defn z 
  [idx]
  (prn [:z idx])
  (Thread/sleep 1000)
  (#'z (inc idx)))
(future (z 0))
;; [:z 0]
;; [:z 1]
;; [:z 2]
(defn z 
  [idx]
  (prn [:z :changed idx])
  (Thread/sleep 1000)
  (#'z (inc idx)))
;; [:z :changed 3]
;; [:z :changed 4]

"在 java" 中,它会这样做

public static Object invokeStatic(Object idx) {
    prn(["z", idx ]);
    return ((IFn) RT.read("user/z")).invoke(idx + 1);
}
...