Skip to content

Instantly share code, notes, and snippets.

@rwilson
Last active March 21, 2016 23:10
Show Gist options
  • Save rwilson/b04a57784ddbe060a227 to your computer and use it in GitHub Desktop.
Save rwilson/b04a57784ddbe060a227 to your computer and use it in GitHub Desktop.
Clojure: when to use the var macro?
;;; I went looking for details on when it is appropriate to use the var macro (#’).
;; Here are a couple functions to set the context:
(defn something [fn x] (fn x))
(defn cube [x] (* x x x))
;; Now, a repl stack to demonstrate:
foo.core=> (something cube 4)
64
foo.core=> (something #'cube 4)
64
;;; Assuming that rarely are there "redundant" behaviors without purpose, I got wondering when
;;; it was appropriate to use one form vs the other. So, here’s some info:
;;;
;;; #’ is the var macro, same as (var x), and “When used it will attempt to return the referenced var.
;;; This is useful when you want to talk about the reference/declaration instead of the value it represents.”
;;; Quote from this great article: http://yobriefca.se/blog/2014/05/19/the-weird-and-wonderful-characters-of-clojure/
;; It can be seen with:
foo.core=> cube
#<core$cube foo.core$cube@1fa547d1>
foo.core=> #'cube
#'foo.core/cube
foo.core=> @#'cube
#<core$cube foo.core$cube@1fa547d1>
;;; The first form resolves the value from the var directly
;;; The second form, resolves the symbol “cube” to the Var #'foo.core/cube
;;; The third form, while being obviously redundant, explicitly resolves the symbol “cube”
;;; to the Var #'foo.core/cube, and then dereferences it to get the value
;;;
;;; This is interesting because of its implications when passing functions as arguments to other functions.
;;; If passed as (some-fn some-arg-fn), then the value of some-arg-fn, as resolved at the time some-fn is called,
;;; is passed to some-fn.
;;;
;;; That’s interesting, because by the time some-fn does anything with that argument it receives, it’s possible that
;;; the actual value of some-arg-fn elsewhere could be different. Because the Var some-arg-fn wasn’t passed. The dereferenced
;;; value of the Var some-arg-fn was passed.
;;; On the other hand, if called as (some-fn #'some-arg-fn), then the Var is actually passed, meaning that the value arrived at
;;; by dereferencing some-arg-fn won’t be determined until some-fn actually does the dereferencing.
;;; A more detailed explanation is in this Stack Overflow answer: http://stackoverflow.com/a/9115958/302092
;;; It contains a good explanation about getting from ns -> symbol -> var -> value
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment