Fork me on GitHub
#babashka
<
2020-03-28
>
rickmoynihan13:03:02

I’m curious about using babashka/sci to implement a graalvm command line tool based around a library of mine that uses core.logic. Unfortunately core.logic leverages a lot of JVM tricks etc to make it fast — e.g. protocols / definterface etc… Additionally core.logic programs tend to use macros such as fresh / run etc. I get the feeling this might be a bit beyond sci etc at the minute; and that I might be better creating a sci compatible port of miinkanren, and re-targeting my library on top of that?

borkdude13:03:26

@rickmoynihan it doesn't matter if core.logic itself uses defprotocol, etc. you can still hook it up to sci

borkdude13:03:00

the use case for sci is: you want to make a tool which exposes a Clojure DSL to its users. if that's not important, you can also just build your own graalvm tool

borkdude13:03:24

the Clojure DSL itself cannot use defprotocols, but you can access functions which use protocols behind the scenes

rickmoynihan13:03:25

Yeah was thinking that I’d need to do that

rickmoynihan13:03:25

Does sci support macros though? The DSL I’d like to expose is quite macro heavy at the minute.

borkdude13:03:46

the user can define macros themselves, but you can also hook in macros from the outside

rickmoynihan13:03:30

ok you seem to be confirming what I was hoping then, so I’ll need to: 1. create a new clojure cli app that requires my dsl lib & sci 2. build it with graal 3. Hook my libs macros into sci 4. pass dsl forms into sci 5. profit

rickmoynihan13:03:23

Thanks for confirming all this for me

rickmoynihan15:03:01

If I have an existing defmacro what’s the best way to expose it through sci? The example in the README, seems to be for the macro body itself:

(def do-twice ^:sci/macro (fn [_&form _&env x] (list 'do x x)))

rickmoynihan15:03:07

Is it for example possible to reuse something like clojure.core/when and expose it as mywhen?

rickmoynihan15:03:32

hmm I guess I can do something like: (@#'clojure.core/when nil nil true '(println "hello"))

rickmoynihan15:03:02

Ok this works:

(def mywhen ^:sci/macro (fn [form env test body] (@#'clojure.core/when form env test body)))

(sci/eval-string "(mywhen true (println \"hello\"))" {:bindings {'mywhen mywhen 'println println}})
Would it be worth adding an example like this to the README?

rickmoynihan15:03:28

A macro could build these def proxies easily enough — though I wonder if it might be better to just alter-meta! on the macro vars adding the ^:sci/macro metadata that way… 🤔

rickmoynihan15:03:40

trying it now…

borkdude15:03:42

@rickmoynihan the (def mywhen ^:sci/macro (fn [form env test body] (@#'clojure.core/when form env test body))) approach works, but in general passing existing macros to sci breaks pretty fast, because the symbols in the macro body are resolved against a different namespace than inside sci

rickmoynihan15:03:13

Yeah I was planing on requiring them in my ns too

borkdude15:03:21

then that should pretty much work

borkdude15:03:57

sci.impl.main=> (def mywhen ^:sci/macro (fn [form env test body] (@#'clojure.core/when form env test body)))
#'sci.impl.main/mywhen
sci.impl.main=> (sci/eval-string "(mywhen true (+ 1 2 3))" {:bindings {'mywhen mywhen}})
6
sci.impl.main=> (sci/eval-string "(mywhen false (+ 1 2 3))" {:bindings {'mywhen mywhen}})
nil

rickmoynihan16:03:22

yeah that’s pretty much exactly what I had

rickmoynihan16:03:42

ahh yeah yours is a bit more minimal in bindings

borkdude16:03:43

bindings is just shorthand for {:namespaces {'user ...}} - it stems from the time when there were no namespaces yet

rickmoynihan16:03:59

yeah makes total sense

rickmoynihan16:03:29

bindings and env in lisp interpreters are essentially the same thing right?

borkdude16:03:05

not sure what other lisp interpreters call it

borkdude16:03:36

I guess the word context is used a lot as well 😉

nate18:03:27

This is amazing.

nate18:03:17

Interesting to think of the possibilities of tying into other tools.

nate18:03:31

Instead of always bundling everything in.

borkdude19:03:51

Added basic-auth and session management to the note app example 🙂 https://github.com/borkdude/babashka/#note-taking-app

borkdude20:03:35

it's pretty fun to implement a web-app with only a socket server 😉