Edd Mann Developer

Recreating 'Let' using a Macro in Clojure

Inspired by a good friends recent Gist on how the functionality of the special form let could be achieved using a little Lambda trickery, I decided to write a simple Macro that would do this transformation. It is very interesting to see how concepts such as this can be built up from underlying calculus fundamentals.

(defmacro lets [bindings & body]
`((fn [~@(take-nth 2 bindings)] ~@body) ~@(take-nth 2 (rest bindings))))

(lets [foo "bar" baz 123]
(println foo baz)) ; bar 123
(clojure.walk/macroexpand-all '(lets [foo "bar" baz 123] (println foo baz)))
; ((fn* ([foo baz] (println foo baz))) "bar" 123)

You can see how simple the macro actually is, with the inclusion of only two unquote-splicing actions. I was hoping to also include some of the guards that are present in the let macro using assert-args but sadly this has been made private within the core library.