sci

https://github.com/babashka/SCI - also see #babashka and #nbb
katox 2020-11-06T14:31:32.074400Z

I bumped into this:

(sci/eval-string "(require '[clojure.set :as set]) (set/union {}{})" opts)
=> {}
but
(sci/eval-form (sci/init {}) (edn/read-string "(require '[clojure.set :as set]) (set/union {}{})"))
Execution error (ExceptionInfo) at sci.impl.utils/throw-error-with-location (utils.cljc:52).
Could not resolve symbol: clojure.set
how can I interpret a form previously read by edn/read-string ? Or do I have to use the sci version?

borkdude 2020-11-06T14:33:47.074600Z

let me take a look

borkdude 2020-11-06T14:37:53.075500Z

@katox ah I see. the EDN you read is not well-formed as clojure code due to EDN supporting quotes as single things, they are not related to what follows. It's just an ordinary symbol.

user=> (edn/read-string "'[1 2 3]")
'
compare:
user=> (def form (read-string "(do (require '[clojure.set :as set]) (set/union #{1 2} #{2 3}))"))
#'user/form
user=> (sci/eval-form (sci/init {}) form)
#{1 3 2}

katox 2020-11-06T14:39:58.076400Z

hmm, if I replace the quote symbol with the actual quote function it still doesn't do the thing

borkdude 2020-11-06T14:40:57.076600Z

@katox

user=> (def form (edn/read-string "(do (require (quote [clojure.set :as set])) (set/union {}{}))"))
#'user/form
user=> form
(do (require (quote [clojure.set :as set])) (set/union {} {}))
user=> (sci/eval-form (sci/init {}) form)
{}

borkdude 2020-11-06T14:41:08.076900Z

edn/read-string only reads the first form

katox 2020-11-06T14:41:27.077100Z

right!

katox 2020-11-06T14:41:59.077800Z

what was the original problem - it was a "configuration" file with two functions in it

katox 2020-11-06T14:42:24.078300Z

i wanted to read it in with edn and run those functions through sci (only those)

katox 2020-11-06T14:42:46.079Z

what approach would you use? just read it all using sci parser?

borkdude 2020-11-06T14:43:04.079400Z

@katox I think you can also use edamame for this: it allows parsing EDN++, where ++ is just the amount you need

katox 2020-11-06T14:43:19.079700Z

edn++, nice 😄

borkdude 2020-11-06T14:43:26.079900Z

but you can also just use the sci parser for this

borkdude 2020-11-06T14:44:04.080600Z

https://github.com/borkdude/edamame

👍 1
katox 2020-11-06T14:44:09.080900Z

things like these get tricky soon, you must have a galaxy brain

katox 2020-11-06T14:44:42.081400Z

thanks a lot, I'll try to get that in

katox 2020-11-06T14:45:17.082100Z

another thing - is there a convenience function to import the whole ns into sci :namespaces ?

borkdude 2020-11-06T14:45:37.082600Z

not really, but you can do this using ns-publics + sci/copy-var

katox 2020-11-06T14:46:26.083200Z

I use this

(defn map-sym [ns syms]
  (into {} (map (fn [sym] [sym @(resolve (symbol (name ns) (name sym)))]) syms)))
but kinda too simplistic 🙂

borkdude 2020-11-06T14:47:08.083800Z

that works too. note that if you're compiling down to a native-image, having resolve in a function body isn't great for size

borkdude 2020-11-06T14:47:39.084100Z

but if you're doing this on the top-level it should not be a problem

katox 2020-11-06T14:48:20.084800Z

the ns will be compiled in, the require is there only to alias syms

katox 2020-11-06T14:49:12.085300Z

will alias be better?

borkdude 2020-11-06T14:49:32.085900Z

@katox What I mean is: if you use map-sym only on top-level values, that's ok, but if you use this at run-time in the graalvm binary, it will add 10-20 MB to the binary for nothing

borkdude 2020-11-06T14:49:53.086200Z

See https://github.com/borkdude/edamame

borkdude 2020-11-06T14:50:02.086400Z

Oops, sorry, I mean https://github.com/borkdude/dynaload

borkdude 2020-11-06T14:50:37.087200Z

Resolve holds on to too much stuff, this is why you will get a fatter binary

katox 2020-11-06T14:50:57.087600Z

I see it's about the resolve function itself

borkdude 2020-11-06T14:51:58.088700Z

yes. so:

(def my-namespace (map-sym ...))
is good, but:
(defn foo [x] (get (map-sym ...) x))
is not that great for binary size.

borkdude 2020-11-06T14:53:15.090Z

A relatively simple graalvm binary with java 11 and clojure 1.10.2-alpha3 yields about 11mb. When you accidentally use resolve at runtime it will become 25mb.

katox 2020-11-06T14:54:37.091300Z

The first could do, it's a constant environment. I am just too lazy to enumarate the whole libary ns and top level syms. ns-publics + copy-var should do the same thing (if all symbols are imported)

borkdude 2020-11-06T14:55:00.091700Z

yeah, generating a constant at compile time, that's the way to do it.

👍 1
borkdude 2020-11-06T14:55:29.091900Z

sounds like that works fine.

katox 2020-11-06T14:56:29.092500Z

thanks for insights