6

In the compojure library in the core namespace, I see the following form:

(defn- compile-route "Compile a route in the form (method path & body) into a function." [method route bindings body] `(#'if-method ~method (#'if-route ~(prepare-route route) (fn [request#] (let-request [~bindings request#] (render (do ~@body) request#)))))) 

and

(defmacro GET "Generate a GET route." [path args & body] (compile-route :get path args body)) 

Further up in the file, the if-method and if-route functions are defined with defn-s.

I don't understand the meaning of the #' in this compile-route function though. The docs for (var ...) says:

The symbol must resolve to a var, and the Var object itself (not its value) is returned. The reader macro #'x expands to (var x).

But to me, in the context of what is happening (ie being called from a defmacro), it just sounds like it means the value of the symbol will be returned, which is the same as what substitutability sounds like:

(def x 5) (+ x 7) -> 12 

ie, (+ x 7) expands to, or is the same as, (+ 5 7)

What am I missing here?

2 Answers 2

4

After looking at this for a while, I'm starting to suspect that it has something to do with the fact that the if-method and if-route functions are actually private ((defn- if-route ...)).

Also, for macros, when you do the back-tick quote (" ` ") you are actually getting the fully-namespace-specified symbol in the final expansion:

`(+ 2 3) 

would expand to

(clojure.core/+ 2 3) 

Since these methods are private, they won't be accessible in the normal expansion, therefore the var function is used, to get to the symbol that holds a reference to the actual function that must be invoked at this point in the expansion.

Sign up to request clarification or add additional context in comments.

1 Comment

One more comment: Symbols do not hold references. Vars do. This is a difference to Lisp, IIUC. Symbols are just names and are resolved to Vars by the compiler. The code works, because the Var delegates all .invoke calls to the thing it holds.
3

ring-reload can reload var definitions from files that you keep modifying during development. Since you pass on a (var ...), it is resolved every time you try to read it, and as a consequence the reloaded vars can be re-read on every request. This leads to interactive web development (without needing to compile etc.) If you don't use (var ...) and rather pass the value directly then the reloaded vars will not be passed to the ring URI handlers and hence you cannot simply modify-and-run your code.

Check this blog entry for example:

http://charsequence.blogspot.com/2010/09/interactive-web-development-with.html

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.