2

Let us say we define the function my-function that will print "message1". Next at the repl we define this atom which uses that function.

(def key-func (atom {:func my-function}))

After that I update the function my-function to print "message2". Now when I run ((:func @key-func)) it prints "message1". I end up having to reload the atom. This would lead me to believe that {:func my-function} is not pairing a reference to the actual function with :func rather it is passing a copy of what the function is at that time. So, is it possible to pass a function pointer rather than a copy?

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
Jason Basanese
  • 690
  • 6
  • 20
  • I think I am using the terms pointer and reference correctly, but if I am not please correct me and I will fix the question. – Jason Basanese Nov 15 '16 at 02:52

1 Answers1

3

Short Answer

See this question: When to use a Var instead of a function?

Longer Answer

You are using the atom in a non-standard way. I think the following is closer to what you want:

(defn f1 [] "#1")
(defn f2 [] "#2")


(def my-fn (atom f1))
(println :1 (@my-fn))
(reset! my-fn f2)
(println :2 (@my-fn))

Generates:

:1 #1
:2 #2

Longest Version

This example shows the difference between copying a function vs copying the var that points to the function:

; 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) 

With results:

;-----------------------------------------------------------------------------
;=> 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...

Warning

Having shown how vars behave, please remember it is not good to redefine top-level forms like (def ...) and (defn ...). It is usually best to use an atom, or a local var to hold changing values.

Community
  • 1
  • 1
Alan Thompson
  • 29,276
  • 6
  • 41
  • 48
  • In response to warning: I understand that it is bad practice to redefine top level forms. My case is development where these top-level forms that typically wouldn't change are being reloaded frequently for testing purposes. I wanted the updated functions to be reflected in the state atom which is not reloaded. – Jason Basanese Nov 15 '16 at 12:55