Fork me on GitHub
#sci
<
2021-08-17
>
victorb14:08:52

Trying to wrap the macro http://reagent.co/with-let to be used in SCI, but when using it in eval, it seems to not understand it as a macro or something, as I'm getting a "Could not resolve symbol: t" error with my example. My example execution looks like this: (with-let [t 10] [:div "Nah"]) which makes the error happen. My SCI wrapper looks like this:

(def with-let ^:sci/macro
  (fn [bindings & body]
    `(r/with-let ~bindings ~@body)))
I tried with the [_&form _&env x] argument definition as well from the README, but then it seems it swallows all the args somehow. Not sure what's going on

borkdude15:08:03

@victorbjelkholm429 macros take two extra args indeed, those are mandatory

borkdude15:08:20

(def with-let ^:sci/macro
  (fn [_ _ bindings & body]
    `(r/with-let ~bindings ~@body)))

victorb15:08:55

@borkdude thanks! hm, maybe I'm adding the macro wrongly to the SCI context then? I'm using the :bindings and then just refer to the function with the :sci/macro metadata. Just tried this implementation:

(def with-let ^:sci/macro
  (fn [form env bindings & body]
    (pprint "Inside with-let")
    (pprint form)
    (pprint env)
    (pprint bindings)
    (pprint body)
    `(r/with-let ~bindings ~@body)))
And I'm getting this as output:
"Inside with-let"
[]
[:div "Nah"]
nil
nil
If I pass it (with-let [] [:div "Nah"])

borkdude15:08:03

I don't understand why you are trying to produce r/with-let though, I think you really have to (re-)implement the macro, not wrap it. But this is another problem.

victorb15:08:31

Ah, I see. I'll give reimplementing it a try then

borkdude15:08:39

but this is not the issue you're seeing here

borkdude15:08:57

form should print the entire invocation

borkdude15:08:01

not a vector

borkdude15:08:29

try (with-meta ... {:sci/macro true})

victorb15:08:37

yeah, seems form => binding vector and env ends up being body, so the two first args are not being used (by SCI?)

victorb15:08:29

@borkdude tried this now:

(def with-let
  (with-meta
    (fn [form env bindings & body]
      (pprint "Inside with-let")
      (pprint form)
      (pprint env)
      (pprint bindings)
      (pprint body)
      `(r/with-let ~bindings ~@body))
    {:sci/macro true}))
Same results

borkdude15:08:54

and how did you configure the SCI context / options?

borkdude15:08:01

Please show the entire definition + SCI config + invocation

borkdude15:08:19

as a minimal repro

borkdude15:08:08

or if your code is public, that's fine too

borkdude15:08:40

This should also work in CLJS:

(defn ^:macro with-let [_ _ bindings & body] ...)
(def rns (sci/create-ns 'reagent.core nil))
(def namespaces {'reagent.core {'with-let (sci/copy-var with-let reagent-ns)}})
(def ctx (sci/init {:namespaces namespaces}))

borkdude15:08:27

But so should:

(def with-let ^:sci/macro (fn with-let [_ _ bindings & body] ...))
(def namespaces {'reagent.core {'with-let with-let}})
(def ctx (sci/init {:namespaces namespaces}))

victorb15:08:54

yeah, there is a lot of indirections at play (running Clojure code inside Obsidian via SCI), so trying to strip everything away

borkdude15:08:15

cljs.user=> (def with-let ^:sci/macro (fn [form _ bindings & body] (prn form) `(+ 1 2 3)))
#'cljs.user/with-let
cljs.user=> (sci/eval-string "(with-let [])" {:namespaces {'user {'with-let with-let}}})
(with-let [])
6

borkdude15:08:46

cljs.user=> (defn ^:macro with-let2 [form _ bindings & body] (prn form) `(+ 1 2 3))
#'cljs.user/with-let2
cljs.user=> (sci/eval-string "(with-let2 [])" {:namespaces {'user {'with-let2 (sci/copy-var with-let2 (sci/create-ns 'user nil))}}})
(with-let2 [])
6