babashka

https://github.com/babashka/babashka. Also see #sci, #nbb and #babashka-circleci-builds .
borkdude 2020-11-07T15:38:22.201400Z

I'm considering a .babashka/config.edn or babashka.edn where you can store things like :paths, :classpath-cmd (to calculate a classpath using e.g. clojure or using a bb script itself), :pods: pod specific settings, like where to download them. If you have any input on this, here is the issue: https://github.com/borkdude/babashka/issues/473

hoppy 2020-11-07T17:14:09.205Z

What would be the easiest way to craft something in bb that simply reads a number of edn forms from some file. I must be missing something obvious, but I invariably get off into weeds with needing to have a pushback-reader to use (clojure.edn/read). A bb (or clj) program that reads a file full of edn into memory should be hello world - so I must be missing somthing bigtime.

borkdude 2020-11-07T17:19:03.205500Z

@hoppy so you have multiple values in one file, not like one value inside a vector right?

hoppy 2020-11-07T17:19:29.205900Z

correct, and it's full of maps that are across multiple lines

borkdude 2020-11-07T17:19:41.206200Z

@hoppy In one-liners you can do this:

$ echo '{:a 1} {:a 2}' | bb -I -e "*input*"
({:a 1} {:a 2})

hoppy 2020-11-07T17:20:03.206700Z

yes, but I want to open the file from within the script

borkdude 2020-11-07T17:20:07.206900Z

let me give you the variant that is suitable for scripts

borkdude 2020-11-07T17:21:16.207500Z

$ echo '{:a 1} {:a 2}' | bb -e "(take-while #(not= ::eof %) (repeatedly #(edn/read {:eof ::eof} *in*)))"
({:a 1} {:a 2})

borkdude 2020-11-07T17:21:46.207900Z

when reading from a file, replace *in* with (io/reader file)

hoppy 2020-11-07T17:22:09.208300Z

I thought edn/read needs a pushback reader

borkdude 2020-11-07T17:23:17.208600Z

oh right.

$ echo '{:a 1} {:a 2}' | bb -e "(let [reader  (java.io.PushbackReader. (io/reader *in*))] (take-while #(not= ::eof %) (repeatedly #(edn/read {:eof ::eof} reader))))"
({:a 1} {:a 2})

hoppy 2020-11-07T17:23:49.209100Z

that's usually the sort of thing I come up with as well. Seems a little harsh, but ok.

borkdude 2020-11-07T17:24:29.209500Z

I was considering making this a util function in babashka

hoppy 2020-11-07T17:24:57.209800Z

it seems to be to be a missing bit in http://clojure.java.io frankly

borkdude 2020-11-07T17:25:16.210Z

<http://babashka.io|babashka.io>
;)

hoppy 2020-11-07T17:25:45.210300Z

I'm all for that as well

borkdude 2020-11-07T17:26:54.210700Z

I had an issue for that here, but then decided to close it as documentation could maybe fix that better. https://github.com/borkdude/babashka/issues/613

borkdude 2020-11-07T17:27:26.211400Z

but maybe http://babashka.io which will replace the I/O flags (that some people find confusing) may work

hoppy 2020-11-07T17:29:38.213200Z

it's a tricky spot. putting things in bb that wouldn't be in jvm may cause hardship for peeps that are unknowing using bb as a gateway drug.

borkdude 2020-11-07T17:30:04.213500Z

the way I solve that is publish every namespace as a JVM lib as well

borkdude 2020-11-07T17:30:14.213800Z

e.g. babashka.curl and babashka.process are both JVM libs

borkdude 2020-11-07T17:30:21.214Z

even babashka.pods

hoppy 2020-11-07T17:30:43.214200Z

ok, that's slick

borkdude 2020-11-07T17:34:10.214900Z

we could also make one big babaskha.core or babashka.utils namespace where we accumulate functions that are missing from other core namespaces

borkdude 2020-11-07T17:34:27.215100Z

not sure

hoppy 2020-11-07T17:37:45.216300Z

dunno maybe I'm biased, but it seems like this should be a 1-liner in script space, at least if you would rather edn be the storage format than json or yaml. It's a little to bitey to get this loaded for my taste.

hoppy 2020-11-07T17:38:00.216700Z

no matter how you do it, seems worth doing.

borkdude 2020-11-07T18:43:19.216900Z

this is fun btw: https://grep.app/search?q=edn/read%20%7B%3Aeof%20

borkdude 2020-11-07T18:46:46.218700Z

we could make babashka.edn as a counterpart to clojure.edn and add missing functions. similar for http://clojure.java.io / http://babashka.io. even if those small nss don't contain a lot of functions, they could be bundles in a babashka.misc library that bundles these little namespaces?

borkdude 2020-11-07T18:47:53.219800Z

<http://babashka.io|babashka.io>: push-back-reader
babashka.edn: edn-seq
;;=&gt;
(bedn/edn-seq (bio/push-back-reader (io/reader file)))

borkdude 2020-11-07T18:56:04.221100Z

we could make this easier. and create the pushback reader for you if it isn't one.

(bedn/edn-seq (io/reader file))
Then again, we could also call io/reader on something if it isn't some reader:
(bedn/edn-seq file)

borkdude 2020-11-07T19:06:37.222300Z

(defn edn-seq [reader-coercible]
  (let [reader (cond (instance? java.io.PushbackReader reader-coercible)
                     reader-coercible
                     (instance? java.io.Reader reader-coercible)
                     (java.io.PushbackReader. reader-coercible)
                     :else (java.io.PushbackReader. (io/reader reader-coercible)))
        sentinel (Object.)]
    (take-while #(not (identical? sentinel %))
                (repeatedly #(edn/read {:eof ::eof} reader)))))
I can see why a library would not offer this, e.g. line-seq doesn't, since it depends on the usage when you want the reader to be closed. it's the lazy vs resources problem which is generally better solved with transducers

borkdude 2020-11-07T19:09:35.222500Z

https://grep.app/search?q=edn-seq

borkdude 2020-11-07T19:33:13.223Z

@hoppy At least I added docs here how to translate i/o flags to scripts: https://github.com/borkdude/babashka/blob/master/doc/io-flags.md

hoppy 2020-11-07T19:34:48.223500Z

looks good!