babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
borkdude 2020-12-11T20:35:28.178600Z

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

borkdude 2020-12-11T20:36:57.179400Z

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

borkdude 2020-12-11T20:37:34.180Z

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

nate 2020-12-11T21:59:48.181900Z

(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...

borkdude 2020-12-11T22:11:30.182100Z

right

nate 2020-12-11T22:19:50.182400Z

makes the most sense for library behavior

borkdude 2020-12-11T22:43:55.183400Z

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.

nate 2020-12-11T23:16:05.184600Z

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

borkdude 2020-12-11T23:16:49.185100Z

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

borkdude 2020-12-11T23:17:09.185400Z

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

borkdude 2020-12-11T23:17:15.185600Z

cross-platform solution

nate 2020-12-11T23:19:37.185800Z

oh, gotcha

nate 2020-12-11T23:21:26.187700Z

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. ...

nate 2020-12-11T23:21:42.188100Z

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

borkdude 2020-12-12T16:28:35.202100Z

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"

borkdude 2020-12-12T16:29:14.202300Z

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

borkdude 2020-12-12T16:31:04.202500Z

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

borkdude 2020-12-12T16:32:35.202700Z

A simple REPL invocation:

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

borkdude 2020-12-12T17:00:33.202900Z

$ 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

nate 2020-12-12T17:09:55.208300Z

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.

nate 2020-12-12T17:10:48.209300Z

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

borkdude 2020-12-12T17:11:49.209500Z

Good thoughts

borkdude 2020-12-12T17:12:40.209700Z

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

borkdude 2020-12-12T17:13:01.209900Z

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

borkdude 2020-12-12T17:14:11.210100Z

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

borkdude 2020-12-12T17:16:28.210300Z

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

borkdude 2020-12-12T17:18:22.210500Z

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

borkdude 2020-12-12T17:19:09.210800Z

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

borkdude 2020-12-12T17:21:13.211Z

although :inherit true is probably closer to DWIM

nate 2020-12-12T17:28:49.212400Z

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

borkdude 2020-12-12T17:30:22.213900Z

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

nate 2020-12-12T17:30:50.214500Z

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

nate 2020-12-12T17:31:14.215300Z

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

borkdude 2020-12-12T17:32:39.215500Z

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

nate 2020-12-12T17:34:03.215700Z

ah cool, yes, that makes sense

borkdude 2020-12-12T17:35:35.215900Z

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

borkdude 2020-12-12T17:47:07.216100Z

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

borkdude 2020-12-11T23:25:54.188700Z

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

nate 2020-12-11T23:28:36.189100Z

👍 rest well