Syntax-Quote Alias Resolution
This is a short technical note on a new capability that landed in ClojureScript.
Currently in ClojureScript, if you use syntax-quote on a symbol that is qualified with an alias, resolution does not occur:
cljs.user=> (require '[clojure.string :as string])
nil
cljs.user=> `string/reverse
string/reverse
But, with the change for CLJS-1612, this properly reflects the behavior you'd see in Clojure:
cljs.user=> `string/reverse
clojure.string/reverse
Thomas Jack gets credit for the fix—in this case, a nice change to a line in the compiler does the trick.
You might be asking, what does this get us?
Well, since syntax quote is often used in macros, this issue hasn't really caused much of a problem in the past. Consider a macro namespace like this one:
(ns foo.core
(:require [clojure.string :as string]))
(defmacro reverse-capitalize
[s]
`(-> ~s
string/reverse
string/capitalize))
If you put the above in a .clj
file and use it from JVM ClojureScript, things will work fine, with
(reverse-capitalize "clojurescript")
yielding "Tpircserujolc"
.
But... things won't pan out so well with bootstrap ClojureScript, where macro namespaces are compiled as ClojureScript. In bootstrap, if you
(macroexpand
'(reverse-capitalize
"clojurescript"))
you will get
(string/capitalize
(string/reverse
"clojurescript"))
which won't work (unless you have string
aliased to clojure.string
in the namespace you are expanding into—but relying on something like that would defeat the entire purpose of syntax quote).
With the patch in place, the above macro expands to
(clojure.string/capitalize
(clojure.string/reverse
"clojurescript"))
and thus works perfectly well in bootstrap environments like Planck.