sci

https://github.com/babashka/SCI - also see #babashka and #nbb
mkvlr 2020-12-21T10:26:11.160600Z

I’m looking to convert some macros for usage with sci. See https://github.com/sicmutils/sicmutils/pull/216. I first tried the copy-var approach, that seemed to work fine from Clojure, but not from ClojureScript. Now I’m trying to convert them but not clear on what I need to do.

borkdude 2020-12-21T10:27:15.161900Z

@mkvlr Can you make a small example which allows me to explain how to solve that small example?

mkvlr 2020-12-21T10:27:50.162300Z

@borkdude sure, or do you have some good pointers of macros you converted for sci?

borkdude 2020-12-21T10:28:24.162900Z

@mkvlr sci.impl.namespaces has lots of those.

borkdude 2020-12-21T10:29:00.163600Z

many of those have _ _ as the first two args, this is how you can find them

borkdude 2020-12-21T10:29:14.164Z

in general, a macro is nothing but a function that receives some forms and returns some other forms

borkdude 2020-12-21T10:29:31.164400Z

but it has two extra arguments: form and env, but often these are not used. so they are named _ _

borkdude 2020-12-21T10:30:10.165200Z

a common problem with copying macros is that the source macro is defined in a different namespace than the namespace of the sci environment

borkdude 2020-12-21T10:30:19.165500Z

so the source macro expands into the wrong namespaced symbols

borkdude 2020-12-21T10:30:32.165900Z

I usually solve this by copying the macro and fully qualifying all symbols myself

mkvlr 2020-12-21T10:32:03.166600Z

oh, but I can use quoting and splicing normally?

borkdude 2020-12-21T10:32:42.167100Z

yes, but the syntax quote will resolve the symbols into the namespace where the macro is defined. so this is often the mismatch

borkdude 2020-12-21T10:33:03.167400Z

syntax-quote is handled at clojure read-time, not at sci evaluation time

mkvlr 2020-12-21T10:33:59.168600Z

ok, so just fully-qualify it

borkdude 2020-12-21T10:34:22.169400Z

so:

(ns foo)
(defn foo [_ _] `x)
will expand into (defn foo [_ _] 'foo/x). If your sci namespace is then called bar and you add this macro to it, then you will have a mismatch

mkvlr 2020-12-21T10:34:30.169700Z

and you recommend copying, right? It’s a bit too much of a head-bender for me how this works in ClojureScript with copy-var

borkdude 2020-12-21T10:35:07.170500Z

copying is done to make the thing a var inside sci, so everything var-related works on it. But sci also allows you to just pass the function reference in the namespaces option

borkdude 2020-12-21T10:36:30.171300Z

if vars aren't important to your sci usage, then you can just avoid using sci/copy-var

borkdude 2020-12-21T10:37:09.172400Z

some people (in babashka for example) want to be able to use doc, alter-var-root!, with-redefs, etc

mkvlr 2020-12-21T10:37:11.172500Z

but it will make doc etc work, right? So it’s a plus?

borkdude 2020-12-21T10:38:36.173600Z

it depends. it might also come with some more overhead because on every call the var has to be dereferenced. I'm thinking of a couple of optimizations here: - https://github.com/borkdude/sci/issues/483 - add :direct-linking option (or allow this programmatically from within a sci program)

borkdude 2020-12-21T10:38:59.174200Z

but I think deref-ing a sci var is cheap

borkdude 2020-12-21T10:39:06.174400Z

will have to do some benchmarks

borkdude 2020-12-21T10:39:34.174700Z

in CLJS people are used to not having vars at runtime anyway

borkdude 2020-12-21T10:39:54.174900Z

unless you're in self-hosted

borkdude 2020-12-21T10:40:01.175200Z

so it's a bit of a grey area

borkdude 2020-12-21T10:41:22.175500Z

for macros it's not so important, since macros are usually not re-defined

borkdude 2020-12-21T10:41:35.175800Z

I think I have in fact a couple of macros in sci that aren't vars (just because I didn't bother to make them vars)

borkdude 2020-12-21T10:44:00.176500Z

in short: doing {:namespaces {'foo (with-meta foo {:sci/macro true})}} is fine

borkdude 2020-12-21T10:44:13.176700Z

^ @mkvlr

mkvlr 2020-12-21T10:49:11.177100Z

hmm, and this should work from both Clojure + ClojureScript?

mkvlr 2020-12-21T10:51:11.177300Z

trying…

borkdude 2020-12-21T10:51:13.177500Z

yes

mkvlr 2020-12-21T11:04:55.177800Z

(defn make-sci-namespace [ns-name]
  (into {} (map (fn [[var-name the-var]]
                  (println var-name)
                  [var-name (cond-> @the-var
                              (-> the-var meta :macro)
                              (with-meta {:sci/macro true}))])) (ns-publics ns-name)))

mkvlr 2020-12-21T11:05:02.178100Z

trying this approach now…

mkvlr 2020-12-21T11:06:44.178500Z

but getting stuck on let-coordinates which is imported https://github.com/sicmutils/sicmutils/blob/master/src/sicmutils/env.cljc#L346

mkvlr 2020-12-21T11:07:11.179100Z

ok, but this should work where it’s defined and then just copy it over

mkvlr 2020-12-21T11:07:34.179300Z

indeed there it does work

mkvlr 2020-12-21T11:07:46.179600Z

ok, 💯 I think I’m good

mkvlr 2020-12-21T14:19:09.180800Z

@borkdude I have all my sci namespaces as a map now, but trouble calling my macro. It works from Clojure but not from ClojureScript…

borkdude 2020-12-21T14:19:37.181Z

can you repro this?

borkdude 2020-12-21T14:19:51.181200Z

if you want I can also do a short video call now

mkvlr 2020-12-21T14:20:08.181500Z

oh yes please

borkdude 2020-12-21T14:20:17.181800Z

ok just a minute