Fork me on GitHub
#babashka
<
2020-12-11
>
borkdude20:12:28

I'm currently thinking more about invoking clojure from babashka. This will satisfy the use case when your deps.edn map needs some dynamism, e.g. merging multiple maps together from multiple places, which currently isn't supported with the official clojure. The main question I'm asking right now is: should invoking (babashka.deps/clojure ...) return something or should that function just hand over control to the java process and exit accordingly to its return code. https://github.com/borkdude/babashka/issues/678

borkdude20:12:57

Maybe it's useful to return something and not exit in the case of -Spath, -Stree etc.

borkdude20:12:34

So maybe returning a babashka.process kind of thing and having its API available on the return value could work.

nate21:12:48

(babashka.deps/clojure ...) could hand back the babashka.process handle, so you can call check on it or do something else according to your use case...

nate22:12:50

makes the most sense for library behavior

borkdude22:12:55

The iffy part is that clojure sometimes does create a process (e.g. a REPL, or executing a file) but for some parts it doesn't, e.g. when invoking -Sdescribe or -Spath. So maybe it should only return a process when invoking main or exec.

nate23:12:05

it always starts a process (either bash+java or just bash), so it feels like its ok to always return a babashka.process process

borkdude23:12:49

that's not how it works in babashka because it's going to use borkdude/deps.clj. the bash is just in-process code.

borkdude23:12:09

i.e. no need to install the official clojure CLI, etc.

borkdude23:12:15

cross-platform solution

nate23:12:37

oh, gotcha

nate23:12:26

feels like there should be multiple functions in the namespace then, one for each major mode in the bash cli: 1. run a main 2. execute a function 3. ...

nate23:12:42

and the ones that execute java return a process, the other ones return data

borkdude16:12:35

I think it'd be nice if people can just pass what they're used to on the command line. E.g.:

$ bb '(-> (babashka.deps/clojure ["-M" "-e" "(+ 1 2 3)"] {:out :string}) babashka.process/check :out)'
"6\n"

borkdude16:12:14

$ bb '(-> (babashka.deps/clojure ["-M" "-e" "(+ 1 2 3)"] {:out :inherit}) babashka.process/check) nil'
6

borkdude16:12:04

So maybe for -Stree and some others, we can just document that they won't return a process and users should program accordingly

borkdude16:12:35

A simple REPL invocation:

$ bb '(-> (babashka.deps/clojure [] {:inherit true}) babashka.process/check) nil'
Clojure 1.10.2-alpha2
user=> (System/exit 0)

borkdude17:12:33

$ bb '(babashka.deps/clojure ["-O"])'
----- Error --------------------------------------------------------------------
Type:     java.lang.Exception
Message:  -O is no longer supported, use -A with repl, -M for main, or -X for exec
Location: <expr>:1:1

nate17:12:55

Was thinking about this more. How about the idea of two levels of api? Level 1: DWIM, can just copy/paste in cli args that you would have passed to clojure and it will do the right thing, would sometimes return process or data. Level 2: individual functions for each task type, for deeper integration and control, takes native data structures or args, some functions return process, others return data.

nate17:12:48

Could just do level 1 at first, and see if there's demand for level 2 to crystallize later.

borkdude17:12:49

Good thoughts

borkdude17:12:40

Current impl of 1 never returns data. It either prints to out or it returns a process

borkdude17:12:01

e.g. for -Spath you can use with-out-str

borkdude17:12:11

This is just because I'm re-using borkdude/deps code, not something that necessarily should be the default impl

borkdude17:12:28

But since the Clojure CLI is also printing this stuff, it might make sense

borkdude17:12:22

Maybe :inherit true should then also be the default: so (deps/clojure) will just invoke a Clojure REPL (deps/clojure ["-M" "-e" "(+ 1 2 3)"]) will print 6 to stdout and returns a process (deps/clojure ["-M" "-e" "(+ 1 2 3)"] {:out :string}) prints to a :out :string and returns the process

borkdude17:12:09

but maybe changing the defaults of babashka.process isn't nice

borkdude17:12:13

although :inherit true is probably closer to DWIM

nate17:12:49

Hm, that's a tough one. If you want to mimic bash, every command has inherit true.

borkdude17:12:22

The idea is to have a easy programmatic Clojure launcher. I think deps/clojure will often be the exit point of the script

nate17:12:50

Changing babashka.process's default would be an upheaval. Maybe it should have been called babashka.process.alpha1 . Heh. (Mostly kidding)

nate17:12:14

Yes, I agree that it will likely be the end of the script.

borkdude17:12:39

No, I don't mean changing babashka.process itself, but the options passed to clojure will implictly have :inherit true as default

nate17:12:03

ah cool, yes, that makes sense

borkdude17:12:35

Ah so {:out :inherit :in :inherit :err :inherit is the default and can then be overriden per key via opts. Maybe that works

borkdude17:12:07

$ clojure -M:babashka/dev '(System/exit (:exit @(babashka.deps/clojure)))'
Clojure 1.10.2-alpha2
user=> (System/exit 1)
[email protected] ~/Dropbox/dev/clojure/babashka (babashka-deps*) $ echo $?
1

borkdude23:12:54

basically rewriting the CLI in fns... hmm. I'll contemplate that while sleeping. Thanks.

nate23:12:36

👍 rest well