In attempting to create a Scittle plugin, (sci/copy-var some-macro sci-created-ns)
(where some-macro
is a symbol created by :refer-macros
) results in an "Unable to resolve var" error. Just to be sure: it's not possible to expose macros of an arbitrary cljs-library in a Scittle plugin, right?
To be sure, just re-implement the macro in terms in CLJS as a normal function
and then use :sci/macro
as metadata on that function to expose it to sci
(defn my-macro [_form _env x y & zs] `(do ...))
(with-meta my-macro {:sci/macro true})
I cannot get this to work:
(ns scittle.makro-plugin
(:require
[sci.core :as sci]
[scittle.core :as scittle]))
(defn add-low-fn [_env _form x y & zs] `(str "__" ~x ~y ~zs))
(def add-low-makro (with-meta add-low-fn {:sci/macro true}))
(def rns (sci/create-ns 'makro-plugin.core nil))
(def makro-plugin-namespace
{'add-low-fn (sci/copy-var add-low-fn rns)
'add-low-makro (sci/copy-var add-low-makro rns)})
(scittle/register-plugin!
::makro-plugin
{:namespaces {'makro-plugin.core makro-plugin-namespace}})
add-low-makro
behaves the same way as add-low-fn
. Do I need to add something in order to SCI recognise a macro?you should not use copy-var
with add-low-makro
as it only copies the var metadata to the sci var
@markus.agwin So:
scittle.makro-plugin=> (defn add-low-fn [_env _form x y & zs] `(str "__" ~x ~y ~@zs))
#'scittle.makro-plugin/add-low-fn
scittle.makro-plugin=> (sci/eval-string "(add-low-makro 1 2 3 4)" {:bindings {'add-low-makro (with-meta add-low-fn {:sci/macro true})}})
"__1234"
This also works:
scittle.makro-plugin=> (defn ^:macro add-low-fn [_env _form x y & zs] `(str "__" ~x ~y ~@zs))
#'scittle.makro-plugin/add-low-fn
scittle.makro-plugin=> (sci/eval-string "(add-low-makro 1 2 3 4)" {:bindings {'add-low-makro (sci/copy-var add-low-fn rns)}})
"__1234"
Great! For the record, this works now:
(ns scittle.makro-plugin
(:require
[sci.core :as sci]
[scittle.core :as scittle]))
(defn add-low-fn [_env _form x y] `(str "_" ~x ~y))
(defn ^:macro add-low-makro [_env _form x y] (add-low-fn _env _form x y))
(def rns (sci/create-ns 'makro-plugin.core nil))
(def makro-plugin-namespace
{'add-low-fn (sci/copy-var add-low-fn rns)
'add-low-makro (sci/copy-var add-low-makro rns)})
(scittle/register-plugin!
::makro-plugin
{:namespaces {'makro-plugin.core makro-plugin-namespace}})
:thumbsup:
@borkdude is env
meant to be empty when I print it via
(defn add-low-fn [form env x y]
`(str "_ form: " ~(str form) " env: " ~(str env) ~x ~y))
? (at least I got the form<->env order right this time)it depends where you call it from
it contains the locals
these arguments are called &form
and &env
in normal Clojure macros
But in this specific Scittle example I cannot improve my code to (for example) have the name of some namespace appear via (:name (:ns env)), right?
Maybe this example helps? https://gist.github.com/borkdude/c97da85da67c7bcc5671765aef5a89ad
that helps, thank you!