Fork me on GitHub
#sci
<
2020-10-29
>
borkdude10:10:08

Made this thing: https://github.com/borkdude/grasp It parses the code using sci and then feeds the sexprs to spec.

sogaiu11:10:55

awesome stuff

Sam Ritchie15:10:46

Q- is it possible (and it may just work, will try soon) to inject forms like Math/sin directly into an SCI context, instead of wrapping it in a fn?

borkdude15:10:50

@sritchie09 you mean like JS interop?

borkdude15:10:23

or both Java + JS interop?

Sam Ritchie15:10:11

trying this now...

Sam Ritchie15:10:58

what was I doing, asking... it just works

Sam Ritchie15:10:06

well, in JS it does!

borkdude15:10:32

I recommend looking at the interop tests: https://github.com/borkdude/sci/blob/master/test/sci/interop_test.cljc At the end there are specific tests for JS as well

Sam Ritchie15:10:34

Looks like it will work if I manually sub in Math/cos etc in Clojure, with a postwalk

Sam Ritchie15:10:50

and "just works" in the JS version, since Math/cos is a function

Sam Ritchie15:10:12

but on the JVM, if I provide a bare Math/cos in the bindings map, I get (of course)

Sam Ritchie15:10:12

Unable to find static field: cos in class java.lang.Math

Sam Ritchie15:10:18

and if I quote it:

Sam Ritchie15:10:20

Execution error (IllegalArgumentException) at sci.impl.interpreter/eval-special-call (interpreter.cljc:546).
No matching clause: Math/cos

borkdude15:10:53

@sritchie09 In CLJ you need to add {:classes {'java.lang.Math Math} :imports '{Math java.lang.Math}}

borkdude15:10:02

and then you can do interop with those classes

Sam Ritchie15:10:26

okay, yesss, will try. Thanks @borkdude

borkdude15:10:25

in CLJS it works similarly:

$ clj -A:test -Sdeps '{:deps {org.clojure/clojurescript {:mvn/version "1.10.597"}}}' -m cljs.main -re node
WARNING: When invoking clojure.main, use -M
ClojureScript 1.10.597
cljs.user=> (require '[sci.core :as sci])
nil
cljs.user=> (sci/eval-string "(Math/pow 2 3)" {:classes {'Math js/Math}})
8

Sam Ritchie16:10:34

interesting, @borkdude giving this a whirl now:

Sam Ritchie16:10:45

(let [f (->> (sci/init
              {:classes {java.lang.Math 'Math}
               :imports {'Math java.lang.Math}})
             (sci/eval-string "(fn [x] (+ 1 (Math/cos x)))"))]
  (f 0.5))

Sam Ritchie16:10:55

gives me Could not resolve symbol: Math/cos

Sam Ritchie16:10:16

the quotes aren't exactly as you specified of course

borkdude16:10:57

@sritchie09 The imports should be all quoted

borkdude16:10:16

Also classes should be symbol -> class

borkdude16:10:48

{:classes {'java.lang.Math Math}}

borkdude16:10:00

{:imports '{Math java.lang.Math}}

Sam Ritchie16:10:32

taking a look at the interop tests now

Sam Ritchie16:10:43

eval-string needs the dict

Sam Ritchie16:10:53

passing an already-initialized context caused the failure

Sam Ritchie16:10:16

(let [f (sci/eval-string
         "(fn [x] (+ 1 (Math/cos x)))"
         {:classes {'java.lang.Math Math}
          :imports '{Math java.lang.Math}})]
  (f 0.5))

borkdude16:10:14

these options work with sci/init as well

Sam Ritchie16:10:38

for sure, I just mean that the form I just pasted works, but

Sam Ritchie16:10:45

(let [f (sci/eval-string
         "(fn [x] (+ 1 (Math/cos x)))"
         (sci/init
          {:classes {'java.lang.Math Math}
           :imports '{Math java.lang.Math}}))]
  (f 0.5))

Sam Ritchie16:10:58

does not (map wrapped in sci/init before passing it to eval-string

Sam Ritchie16:10:17

taking my baby steps

borkdude16:10:34

yeah, that doesn't work. eval-string takes a string + opts. eval-string* takes a ctx (produced by init) and a string

borkdude16:10:12

eval-string = init + eval-string*

Sam Ritchie16:10:04

now here is the hail mary:

Sam Ritchie16:10:05

(let [f (sci/eval-form
         (sci/init
          {:classes {'java.lang.Math Math}
           :imports '{Math java.lang.Math}
           :bindings {'cos 'Math/cos}})
         '(fn [x] (+ 1 (cos x))))]
  (f 0.5))

Sam Ritchie16:10:33

is it possible to go one step further, and use bindings to sub in a form like Math/cos , that's not a fn but a static field

Sam Ritchie16:10:40

this gives No matching clause: Math/cos

Sam Ritchie16:10:15

(thanks for the help here, happy to go hunt on my own too)

borkdude16:10:50

in that case you should just write wrapper functions {:bindings {'cos (fn [x] (Math/cos x))}}

Sam Ritchie16:10:53

👍 that's what I'm doing now and it works great. I didn't know if I could get some speedup by not doing this

Sam Ritchie16:10:01

(which maybe is true in Clojurescript, since I can use a bare Math/cos

borkdude16:10:00

@sritchie09 If you're looking to avoid boilerplate, you can write a macro

👍 3