我们假设我们定义了将打印my-function
的函数"message1"
。
接下来在repl中我们定义了使用该函数的原子。
(def key-func (atom {:func my-function}))
之后,我更新了my-function
函数以打印"message2"
。
现在,当我运行((:func @key-func))
时,它会打印"message1"
。我最终不得不重新加载原子。这会让我相信{:func my-function}
没有将实际函数的引用与:func
配对,而是传递了当时函数的副本。那么,是否可以传递函数指针而不是副本?
TLDR;
(defn my-func [] (print "message1"))
(def key-func (atom {:func my-func}))
(defn my-func [] (print "message2"))
((:func @key-func)) ;prints message1 instead of message2
答案 0 :(得分:3)
请参阅此问题:When to use a Var instead of a function?
您正在以非标准方式使用原子。我认为以下内容更接近您想要的内容:
(defn f1 [] "#1")
(defn f2 [] "#2")
(def my-fn (atom f1))
(println :1 (@my-fn))
(reset! my-fn f2)
(println :2 (@my-fn))
生成:
:1 #1
:2 #2
此示例显示复制函数与复制指向函数的var之间的区别:
; This will not work, since his-fn saves a ref to the
; immutible "All yours baby!" function
(newline)
(println "-----------------------------------------------------------------------------")
(defn your-fn [] (println "All yours baby!"))
(your-fn) ;=> "All yours baby!"
(def his-fn your-fn)
(his-fn) ;=> "All yours baby!"
(defn your-fn [] (println "And it still is!"))
(his-fn) ;=> "All yours baby!"
; This will work, since both his-fn and her-fn save a reference
; to the var `your-fn`, which in turn points to first to
; one function and then to a second function.
(newline)
(println "-----------------------------------------------------------------------------")
(defn your-fn [] (println "All yours baby!"))
(your-fn)
(def his-fn (var your-fn))
(def her-fn #'your-fn)
(his-fn)
(her-fn)
; change what var "your-fn" points to
(defn your-fn [] (println "And now you belong to me..."))
(his-fn)
(her-fn)
结果:
;-----------------------------------------------------------------------------
;=> All yours baby!
;=> All yours baby!
;=> All yours baby!
-----------------------------------------------------------------------------
;=> All yours baby!
;=> All yours baby!
;=> All yours baby!
;=> And now you belong to me...
;=> And now you belong to me...
在展示了vars的行为方式后,请记住重新定义(def ...)
和(defn ...)
等顶级表单并不好。通常最好使用原子或局部变量来保持变化值。