@borkdude does that compile w/ warnings?
it doesn't compile, it throws at the analysis stage, you can't execute it.
Posted an issue about it here: https://clojure.atlassian.net/browse/CLJS-3212
k thanks
I might have a look at it, but probably not before ClojureD
For now I just changed my macro into two macros
But @borkdude thatโs not supposed to work, right? (It defines a macro and then uses it from the same namespace.)
(The arity is always wrongโit only has a runtime check that you see when a multiarity definition is involved.)
The reason you are seeing -1 has to do with the missing two hidden parameters the compiler supplies. (1 - 2 = -1)
@mfikes one is &env
, what's the other one?
&form
TIL
What's the use case for &form
?
It is less used. ClojureScript is just following Clojure for this, FWIW.
I can't recall a use case for &form
off the top of my head. ๐
I bet there is one out there in the wild.
grabbing its meta
logging
@mfikes fwiw, this example is adapted from a codebase with a that works in normal CLJS, but just not in self-hosted CLJS (lumo, planck). if you can provide me with a multi-arity macro example that is supposed to work, that would be cool
The str
macro is one, for example...
That code shouldn't work in normal CLJS, right?
Fundamentally, it is a question of defining a macro in a macros namespace and then using it from a consuming namespace.
let me just get the failing code
By "shouldn't work in normal CLJS", I should have said "has undefined behavior in normal CLJS"
this is the diff I had to make to get it working with self-hosted CLJS:
https://github.com/borkdude/sci/commit/fac2aa8c43091da8aca0f7a45e7a417df0c2ad13#diff-2d9a9848391e25828d94fe11d6ed40d4
so I had to split the copy-var
macro into two macros
the diff contains more stuff, but that's one of the things I did
@mfikes :
(ns foo
#?(:require-macros [foo :refer [multi-arity-macro]]))
(defmacro multi-arity-macro
([x] [x])
([x y] [x y]))
(println (multi-arity-macro 1))
(println (multi-arity-macro 1 2))
$ plk -f /tmp/foo.cljc
WARNING: foo is a single segment namespace at line 1
Execution error (Error) at (<cljs repl>:1).
Invalid arity: -1
What about this example?is that not shadowing foo/multi-arity-macro
(macro) with foo/multi-arity-macro
(fn) ?
Isn't that code calling the macro in the same namespace when definining it (and yet again later in the runtime namespace)?
yeah defmacro
should go into reader conditional :clj
it is, that's why I also wrap this macro in my project:
(defmacro deftime
"Private. deftime macro from <https://github.com/cgrand/macrovich>"
[& body]
(when #?(:clj (not (:ns &env))
:cljs (when-let [n (and *ns* (ns-name *ns*))]
(re-matches #".*\$macros" (name n))))
`(do ~@body)))
but that doesn't prevent the error from happening in self-hosted CLJS
or not? ๐ I think ns gets $macros
suffix...
@bronsa In self-hosted ClojureScript, macros are defined in a separate synthetic pseudo namespace. (In this case named foo$macros
). So there can be two separate vars.
TIL
The need to do this arises in self-hosted because everything is executing in the same execution environment, whereas in JVM-based ClojureScript you have the JS / JVM barrier to keep things separate.
so just moving the macro to a .clj file will probably work, ignoring the intricacies of .cljc and self-hosted?
Yes, that would work with self-hosted, if I'm understanding what you are suggesting. The rule is simply that you need to define a macro in a macros namespace, but then call it from a runtime namespace, however you achieve that.
hmm, just fyi, this does seem to work: foo/macros.cljc:
(ns foo.macros
#?(:cljs
(:require-macros
[foo.macros :refer [deftime]])))
(defmacro deftime
"Private. deftime macro from <https://github.com/cgrand/macrovich>"
[& body]
(when #?(:clj (not (:ns &env))
:cljs (when-let [n (and *ns* (ns-name *ns*))]
(re-matches #".*\$macros" (name n))))
`(do ~@body)))
foo.core:
(ns foo.core
(:require [foo.macros :as macros])
#?(:cljs (:require-macros [foo.core :refer [multi-arity-macro]])))
(macros/deftime
(defmacro multi-arity-macro
([x] `~[x])
([x y] `~[x y])))
(defn foo []
(multi-arity-macro 1))
REPL session:
$ plk
ClojureScript 1.10.520
cljs.user=> (require '[foo.core :as foo] :reload)
nil
cljs.user=> (foo/foo)
[1]
which reflects what I had in my project, so the issue must be somewhat more subtle
I'll close the issue and I'll report again when I have more info