20

Occasionally when looking at other people's Clojure code, I see a function defined via defn and then called using the var-quote syntax, e.g.:

user> (defn a [] 1)
#'user/a
user> (a)   ; This is how you normally call a function
1
user> (#'a) ; This uses the var-quote syntax and produces the same result
1

For the life of me I can't figure out the difference between these two ways of calling a function. I can't find anything in the evaluation documentation to say what happens when the operator of a call is a var that might suggest why the second form would be preferred. They both seem to respond in the same to binding assignments and syntax-quoting.

So, can somebody please provide a code sample that will illustrate the difference between (a) and (#'a) above?

Edit: I know that var-quote can be used to get to a var that's shadowed by a let lexical binding, but that doesn't seem to be the case in the code that I'm looking at.

Alex
  • 13,811
  • 1
  • 37
  • 50

2 Answers2

23

(#'a) always refers to the var a, while (a) can be shadowed by local bindings:

user> (defn a [] 1)
#'user/a
user> (let [a (fn [] "booh")] [(a) (#'a)])
["booh" 1]

But most actual uses of var-quote / function call are not calling the var-quote expression directly, but instead cache its value so that higher-order constructs refer to the current value of var a instead of its value when passed in:

(defn a [] 1)
(defn my-call [f] (fn [] (+ 1 (f))))
(def one (my-call a))
(def two (my-call #'a))
(defn a [] 2)

user> (one)
2
user> (two)
3

This is mostly useful for interactive development, where you're changing some function that gets wrapped in a bunch of other functions in other packages.

Joost Diepenmaat
  • 17,633
  • 3
  • 44
  • 53
8

The second form allows you to circumvent the privacy restrictions that clojure puts in place.

So, for instance, if you develop a library with private functions, but want to test them from a separate namespace, you cannot refer to them directly. But you can get to them using the var quote syntax. It's very useful for this.

Privacy is clojure is, in essence, a form of automatic documentation, as opposed to the privacy you see in Java. You can get around it.

user> (defn- a [] 1)
#'user/a
user> (ns user2)
nil
user2> (user/a)
CompilerException java.lang.IllegalStateException: var: #'user/a is not public,    compiling:(NO_SOURCE_PATH:1) 
user2> (#'user/a)
1
user2> 
Phil Lord
  • 2,917
  • 1
  • 20
  • 31
  • Good point - now that you mention it I remember having done this myself in the past. But the code I'm looking at is calling a non-private fn, so I think avoiding the caching of the currently-bound value is the more likely explanation. – Alex Feb 08 '13 at 17:16
  • Because the code is in a private repo. I posted a general question, got two good answers, and can only accept one, so I accepted the one that I felt better answered the general case. – Alex Feb 11 '13 at 15:45