Skip to content

Latest commit

 

History

History
70 lines (49 loc) · 1.67 KB

CHEATSHEET.md

File metadata and controls

70 lines (49 loc) · 1.67 KB

Macros workshop cheat sheet

Defining macros

(defmacro macro-name [& args] 
	...)

Quoting

Quoting prevents the form following the single-quote sign from being evaluated:

user=> (def my-list '(1 2 3))

Syntax-quote

Like quote in that it prevents the evaluation of the form following its operator (`). The difference is that it attempts to namespace-qualify all symbols in the given form:

user=> `(+ my-list) 
;; (clojure.core/+ user/my-list)

Unquoting

In a quoted form, unquote (~) forces the evaluation of the form following it at macro-expansion time:

user=> `(+ ~my-list) 
;;(clojure.core/+ (1 2 3))

Unquote-splicing

In a quoted form, unquote-splicing (~@) forces the evaluation of the form - which is assumed to be a list - and unpacks its content in the position it is used:

user=> `(+ ~@my-list) 
;; (clojure.core/+ 1 2 3)

Debugging

The built-in macroexpand function expands the given quoted form until it doesn't represent a macro any longer:

user=>  (macroexpand '(cond 
                        (even? 2) "even"
                        :else "odd"))
               
;; (if (even? 2)
;;   "even"
;;   (clojure.core/cond :else "odd"))               

Sometimes it's useful to recursively expand macros until the form can't be expanded further. The function macroexpand-all from the clojure.walk namespace does just that:

user=> (require '[clojure.walk :as w])
user=> (w/macroexpand-all '(cond
                            (even? 2) "even"
                            :else "odd"))
                            
;; (if (even? 2)
;;   "even"
;;   (if :else "odd" nil))