This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
Hi, any idea why this macro works in clj but not in bb, I'm trying to def some stuff at compile time, but bb complains clojure.lang.ExceptionInfo: Var name should be simple symbol.
(defmacro mydef
[]
(let [some-vals-need-computing [1 2 3]]
`(def myvar ~some-vals-need-computing)))
I would guess that it's because def
is a special form that gets special treatment in clj... I think the symbol in the syntax quote should be ~'myvar
to ensure that the argument to def is an unqualified symbol (because syntax quote would typically try to qualify the symbol)
when i macroexpland on the original version, it did expand to a full qualified var in bb, but it blow up when I actually use it. werid
Sorry I don't quiet follow, what is exactly allowed but not officially allowed? And how is that related to my case here?
according to <https://clojure.org/guides/learn/syntax#_def>, the argument to def
should be a 'simple' symbol (no namespace), and def
should create that var is the current ns. So, the fact that syntax quoting puts an ns on the symbol should probably 'break', but in the special case where the ns happens to be the current ns, it works in clj (but not in bb). So, the ~'myvar
ensures that the def
statement that gets created doesn't have a ns on the symbol.
Consider this:
(defmacro mydef
[]
(let [some-vals-need-computing [1 2 3]]
`(def myvar ~some-vals-need-computing)))
#'user/mydef
user=> (ns foo)
nil
foo=> (user/mydef)
Syntax error compiling def at (REPL:1:1).
Can't refer to qualified var that doesn't exist
So while your macro works, it only works if you use it from the same namespace in clj, which is pretty brittle. Best to avoid it
I can relax the check in SCI to make it behave like JVM Clojure though, but it's not the case today and I doubt it is a good relaxation
I just read this code: https://github.com/clojure/clojure/blob/501348deb1e49736f3c49f2c177bcff947fe3a17/src/jvm/clojure/lang/Compiler.java#L532-L543 and it does seem an intended choice. I'd also check with CLJS too see what they do
Apparently CLJS supports it too:
cljs.user=> (def cljs.user/dude 1)
#'cljs.user/dude
cljs.user=> (def user/dudex 2)
Unexpected error (ExceptionInfo) compiling at (<cljs repl>:1:1).
Can't def ns-qualified name in namespace user at line 1
cljs.user=> (ns user)
WARNING: user is a single segment namespace at line 1
nil
user=> (ns cljs.user)
nil
cljs.user=> (def user/dudex 2)
Unexpected error (ExceptionInfo) compiling at (<cljs repl>:1:1).
Can't def ns-qualified name in namespace user at line 1
I'll make a SCI issue to support it in SCI too then, but currently you have to use ~'my-var