sci

Lone Ranger 2022-10-10T18:16:02.327549Z

Can anyone point to some code that has #sci AND #clojure / #clojurescript compatible macros? Is there an easy trick to it? For instance, writing macros for #sci requires writing a ^:sci/macro function, whereas for normal clj/cljs it requires a normal macro written in clj. There's no #?(:sci ...) .cljc reader conditional (as far as I am aware (yet)). So curious if there is a best practice here to ship a library that is sci/#babashka / #clojure / #clojurescript compatible?

borkdude 2022-10-10T18:18:25.994159Z

@goomba It depends what you want to achieve. In bb and clojure there are no differences between macros

borkdude 2022-10-10T18:20:46.978589Z

But since there is no guarantee that a macro exists as a compiled thing in JS once you compiled your CLJS you often have to copy the macro code to a .cljs file if you want to configure it to work with SCI as pre-compiled macros. There is AFAIK no way around this.

borkdude 2022-10-10T18:21:29.547849Z

But nbb, which is made with SCI, can run macros from source as well

borkdude 2022-10-10T18:22:51.107649Z

So this is the config for promesa, which is a macro-heavy library: https://github.com/babashka/sci.configs/blob/main/src/sci/configs/funcool/promesa.cljs This configured is re-used in #scittle and #nbb and some other projects

Lone Ranger 2022-10-10T18:30:55.867109Z

Interesting. Now something like this: https://github.com/babashka/sci.configs/blob/main/src/sci/configs/funcool/promesa.cljs#L143 I'm assuming that will be treated like a regular function in a non sci context?

borkdude 2022-10-10T18:31:54.551749Z

Yes

Lone Ranger 2022-10-10T18:32:02.351369Z

worrrd

Lone Ranger 2022-10-10T18:32:22.354519Z

ok that makes that easy

Lone Ranger 2022-10-10T18:32:26.231599Z

just write all macros like that

borkdude 2022-10-10T18:32:45.007329Z

except in JVM clojure

borkdude 2022-10-10T18:32:55.899449Z

there they behave like proper macros

borkdude 2022-10-10T18:33:04.136739Z

but this is a .cljs file so it's just different there

peterdee 2022-10-10T20:34:37.806869Z

I am a little unclear how macros work in sci with cljs. (def do-twice ^:sci/macro (fn [_&form _&env x] (list 'do x x))) That seems okay, but: (sci/eval-string "(do-twice (f))" {:bindings {'do-twice do-twice 'f #(println "hello")}}) I can see how that would work with one use of do-twice in the eval string, but what if there is more than one?

borkdude 2022-10-10T20:36:17.625799Z

Do you mean with more than one:

(do-twice (f))
(do-twice (f))
?

peterdee 2022-10-10T20:36:56.166109Z

Yes, perhaps with different arguments.

borkdude 2022-10-10T20:37:12.649739Z

Why would that be a problem?

peterdee 2022-10-10T20:37:58.231489Z

I must be missing something. The :bindings map seems to be referring to a single use of macro.

borkdude 2022-10-10T20:38:18.890039Z

No, the bindings map is just a map of symbol to function

borkdude 2022-10-10T20:38:27.197879Z

And this function (macro) can be called as many times as you want

peterdee 2022-10-10T20:40:09.313429Z

I think maybe it is the 'f in the map that is is throwing me off.

borkdude 2022-10-10T20:43:36.711659Z

ok, yeah, f is just a function reference

borkdude 2022-10-10T20:43:58.422489Z

Similar to this:

(def f #(println :hello))
(f) (f) (f)

borkdude 2022-10-10T20:44:20.550129Z

But now as {'f #(println :hello)}

peterdee 2022-10-10T20:45:34.910789Z

Got it. Thanks!