macroexpand-all

clojure.walk

  • (macroexpand-all form)
Recursively performs all possible macroexpansions in form.

2 Examples top

  • user=> (use 'clojure.walk)
    user=> (macroexpand-all '(-> c (+ 3) (* 2)))
    (* (+ c 3) 2)
  • user=> (use 'clojure.walk)
    
    ; tryclj.com and lazybot on #clojure get the following wrong
    user=> (let [-> inc] (-> 5)) 
    6
    
    ; Below macroexpansion is supposed to result in equivalent code to the above
    user=> (macroexpand-all '(let [-> inc] (-> 5)))
    (let* [-> inc] 5)
    user=> (let* [-> inc] 5)
    5
    
    ; However, as is clear above, it does not
Log in to add / edit an example.

See Also top

Log in to add a see also.

Plus_12x12 Minus_12x12 Source clojure/walk.clj:123 top

(defn macroexpand-all
  "Recursively performs all possible macroexpansions in form."
  {:added "1.1"}
  [form]
  (prewalk (fn [x] (if (seq? x) (macroexpand x) x)) form))
Vars in clojure.walk/macroexpand-all:
Used in 0 other vars

Comments top

3 comment(s) for macroexpand-all.

DO NOT USE THIS FUNCTION, it doesn't handle special forms at all, and, as such, does not in fact expand into the ultimate macroexpansion of the form.

For example,

(require '[clojure.walk :as walk])
(println (walk/macroexpand-all '(quote (let [a 1] a))))

Will print

(quote (let* [a 1] a))

When the correct answer is

(quote (let [a 1] a))

Showing an utter unawareness of proper handling of special forms

DO NOT USE THIS FUNCTION

@Sgeo - let is just a macro for let*:

(clojure.repl/source let) =>

(defmacro let
"binding => binding-form init-expr

 Evaluates the exprs in a lexical context in which the symbols in
 the binding-forms are bound to their respective init-exprs or parts
 therein."
 {:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]}
 [bindings & body]
 (assert-args let
     (vector? bindings) "a vector for its binding"
     (even? (count bindings)) "an even number of forms in binding vector")
  `(let* ~(destructure bindings) ~@body))

(quote (let [a 1] a)) is '(let [a 1] a) which evaluates to a list containing the symbol let, a vector [a 1], and a symbol a. In this context, the (let [a 1] a) is not code, but mere data, and as such, should not be macroexpanded at all, anymore than a string like "(-> a b c)" should be macroexpanded into "(c (b a))" (and yes, I know that's not the exact macroexpansion).

Log in to add a comment.