clojuremacrosclojurescriptread-eval-print-loop

What difference between syntax-quote in Clojure and syntax-quote in Clojurescript?


In Clojure REPL:

(macroexpand-1 `(sum 2 1)) ; (user/sum 2 1)

In Clojurescript REPL:

(macroexpand-1 `(sum 2 1)) ; AssertionError: Assert failed: Argument to macroexpand-1 must be quoted

Why it happens? Can you explain evalutation process in Clojurescript please?


Solution

  • In Clojure, macroexpand-1 can be a function, because Clojure has access to the compiler at runtime, so macroexpand-1 can inspect any list you construct. Clojurescript is compiled to Javascript, and doesn't have access to the compiler at runtime. So macroexpand is only useful at compile-time, and must be a macro in order to run then. It therefore doesn't evaluate its argument, and needs it to be a literal quoted list.

    You might now ask: "Doesn't syntax-quote return a quoted list?". But it doesn't. It returns some expression that evaluates to the right list; in principle it could return a quoted list when you don't use any unquoting, but in practice it doesn't. You can see this in the repl by quoting a syntax-quoted expression, to see its expansion instead of evaluating it:

    In a Clojure repl:

    user=> '`(sum 1 2)
    (clojure.core/seq (clojure.core/concat (clojure.core/list (quote user/sum)) (clojure.core/list 1) (clojure.core/list 2)))
    

    In a Clojurescript repl:

    user=> '`(sum 1 2)
    (cljs.core/sequence (cljs.core/concat (clojure.core/list (quote cljs.user/sum)) (clojure.core/list 1) (clojure.core/list 2)))