Clojure functions and gensym

I have a question about some code in the Clojure compojure library.

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


I've only seen gensyms used in the context of macros, where they are used to avoid collisions between the bindings used in the macro and bindings in the local scope.

I would have thought that since the above is a function and not a macro, it is immune to this. So I'm wondering what the rationale is for writing this function as a macro.

(If you're interested, I checked the commit history to see if this function was originally recorded as a macro. It isn't.)


source to share

2 answers

Although what you see is a function, not a macro, it is a function that generates Clojure code . (This will almost certainly be called from within a macro.) And not only generates code, but also inserts code that is passed as an argument body

into the generated code. This is why name collisions should be avoided.

While not a macro, it does the same thing as macros and uses gensym for the same reason.



Gensyms (notation -#

at least) are not used in the context of macros, but in the context of backquote. To more or less provide a macro, symbols that do not allow globally qualified symbols cannot be used within the context of a backquote. While this does not apply, and there is an escape, if you really want the unqualified character, it provides a normal default. For a longer discussion of macrohygiene in Clojure see this blog post.



All Articles