Fork me on GitHub

Joined just to say how much I love the Babashka error handler. Babashka error reports are a thing of beauty. Makes me want to be a poorer programmer. #clojure you paying attention!?

❤️ 3
Drew Verlee14:08:48

Intresting, can you give me an example where you like the error handling more in bb then clojure? At a glance clojure gives better error messages:

user=> (-> "aco"  .isDirectorys)
Execution error (IllegalArgumentException) at user/eval142 (REPL:1).
No matching field found: isDirectorys for class
drewverlee@drewverlee  ~  ls | bb -i '(filter #(-> % io/file .isDirectorys) *input*)'
----- Error --------------------------------------------------------------------
Type:     java.lang.NoSuchFieldException
Message:  isDirectorys

Drew Verlee14:08:34

This one is interesting

drewverlee@drewverlee  ~  bb -i '(inc "2")'
----- Error --------------------------------------------------------------------
Type:     java.lang.ClassCastException
Message:  java.lang.String cannot be cast to java.lang.Number
Location: <expr>:1:1

----- Context ------------------------------------------------------------------
1: (inc "2")
   ^--- java.lang.String cannot be cast to java.lang.Number

----- Stack trace --------------------------------------------------------------
clojure.core/inc - <built-in>
user             - <expr>:1:1
user=> (inc "1")
Execution error (ClassCastException) at user/eval144 (REPL:1).
java.lang.String cannot be cast to java.lang.Number


Your last example is the kind of thing I was referring to. Here's an error from a script I wrote where I got a file path wrong in my configuration. Admittedly a super-simple error (which would have been easily to decipher with Clojure's error handler as well), but I was struck by how clear and usable the error report was.

----- Error --------------------------------------------------------------------
Message:  some_file.csv (No such file or directory)
Location: /home/me/my_script/./send-an-email:166:41

----- Context ------------------------------------------------------------------
162:             (map-indexed make-table-row table-data)]
163:           [:p {:style "font-family: 'Helvetica Neue', Helvetica, Arial; color: #000000"} email-sign-off]]))
165: ;; Build the list of recipients
166: (def recipients (->> (with-open [reader (io/reader (io/file the-csv-file))]
                                             ^--- some_file.csv (No such file or directory)
167:                        (doall (csv/read-csv reader)))
168:                      rest
169:                      flatten
170:                      (remove blank?)
171:                      set

----- Stack trace --------------------------------------------------------------
                 - <built-in>
 - <built-in>
                 - <built-in>
 - <built-in>
                    - <built-in>
... (run with --debug to see elided elements)
clojure.core/set                          - <built-in>
clojure.core/map                          - <built-in>
user                                      - /home/me/my_script/./send-an-email:172:22
clojure.core/map                          - <built-in>
user                                      - /home/me/my_script/./send-an-email:173:22

Drew Verlee00:08:37

That is nice, the error is more expression oriented then line oriented. My guess is because babshaka is more a pure lisp and clojure runs on the jvm? Not sure, i know the clojure team is really aware of the pain points around error messages.


hey 🙂 Is there a babashka pod / integration with clj-kondo? I’m currently piping some analysis output into a babashka script but wondering if I could just somehow call clj-kondo from babashka..


nice, thank you!


Hi 👋 Is there a good one-line technical description of what babashka does?


I see a lot of stuff in the readme about some JVM things being available (how?), and how a faster interpreter is used to sidestep the slower clojure evaluation on the jvm. What is the actual relationship between babashka and the jvm?


The landing page has a summary of the features:


The relationship between bb and JVM is that bb is written using Clojure JVM and exposes features of it, but within an interpreter which is compiled to a native binary with instant startup. It only gives you access to a preselected collection of Java classes


which java classes are available?


someone at work is telling me to use bb to 1) compute the available memory on the system, 2) call a sysctl command to ensure we can set the jvm heap size accordingly, 3) start normal jvm clojure with the heap size options -Xmx


oh okay, I needed


Ah yes you can do that probably using another class. I'm on a bus right now, I'll take a look later tonight


Probably runtime something something


Okay thanks, I could probably just use clojure for this then, but we also need a task manager we might use bb for.


I feel hesitant though. lein for our project, clojure to prep the system for max heap, then bb to manage our run tasks. eek


You can think of bb as a light enough tool as a replacement for Makefile


But with a language that makes sense to Clojure devs


You can start JVM Clojure processes from bb. If you read the tasks tutorial you'll see how that works


those Runtime functions seem related to memory available to the process, not the whole system


Ah darn, you are right. You can shell out to sysctl though like your colleague suggested


Sorry too distracted, have to get off the bus


@U061E2UBT So to recap: you can shell out to any process you want, like you would in bash, capture and parse the string, then call out to other processes, or start a Clojure process. Think of bb as a scripting replacement for bash for people who don't want to spend minutes thinking about nested if/else in bash for longer than a minute.


I can't find a way to get the OS memory from Java other than via some non-public API, so I think you'd have to shell out anyway?


@U061E2UBT It seems this is a lot easier in Node.js though:

$ nbb -e "(do (require '[\"os\" :as os]) (prn (os/totalmem)))"
#nbb is a similar project to babashka but for Node.js (Node babashka, it uses the same interpreter: #sci)


Hope that helps.


since we’re computing our required heap size in project.clj via macroexpansion, we are able to sneak in a system call to ensure the heap size is allowed prior to starting our project’s own jvm

👍 1

but glad to know about bb and nbb, thank you so much for the help


I’m thinking of using babashka to start a bunch of test processes in parallel and then exit with 0/1 based on the child processes exit codes. I think I have a good chunk of this going but I’m not sure how to best parallelize multiple process invocations and wait for all of them to finish. Is there something I don’t know that could make sense here? Maybe I could wire something up with promises but it all feels a bit too involved

Cora (she/her)18:08:08

do you care about handling each process in the order they exit? because if not you can just call babashka.process/process N times and then deref each of the return values after each starts

💡 1
Cora (she/her)18:08:30

if you care about handling them in the order they exit then starting them in futures and pushing the derefed values into a queue would probably work


that actually makes a lot of sense, i somehow thought derefing would cause essentially serial execution but I realize now that it wouldn't

Cora (she/her)19:08:38

oh gosh, that would be a painful API, I'm glad it doesn't work that way simple_smile


hey, is there a way to have nice logging of errors. Using (timbre/error e) yields esoteric results (picrel) 🙂 The file I run catched in (+ 2 "x") - 2 lines of code in file and was started as bb I do like babashkas logging on unhandled expections, but sadly I have to handle mine 🙂


this was the problem I mentioned when building tasks. Is there a reason why bb doesn’t always use the try/catch w/ sci/format-stacktrace for exception handling?


Thanks, thanks @U04V15CAJ will test.


I'm looking into making io.aviso/pretty work well with Babashka, when I have the time.


the colorizing part already works well, I've used that in the past


If it's possible. It's a matter of getting the correct stacktrace, not the actual Java stacktrace (which is all about sci and not about the actual code being executed).


pretty was some of the earliest Clojure code I wrote.


Most of the other Cognitians vilify it.

Jeffrey Bay21:08:30

Hi I'm trying to use the new :^sci.core/error metadata and functions i saw elsewhere, and it seems to be defined with my bb version (1.161), but i'm not able to get a stack trace out of it

Jeffrey Bay21:08:18

mostly i'm looking for the equivalent for this

(clojure.stacktrace/print-stack-trace e)
but with the new, better stack trace

Jeffrey Bay21:08:16

the code i currently have looks like this:

(catch ^:sci.core/error Exception e
      (println (->> e
      (println "command" command "not found - showing beef help:")
      (println "\n\nfailed (see trace before help):\n" (str (.getName (.getClass e)) ":") (ex-message e)))