Fork me on GitHub
#babashka
<
2022-08-16
>
quaeledyn04:08:45

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 java.io.File
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

quaeledyn21:08:35

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 --------------------------------------------------------------------
Type:     java.io.FileNotFoundException
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]]))
164: 
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.

martinklepsch13:08:11

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

martinklepsch16:08:01

nice, thank you!

shaunlebron14:08:52

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

shaunlebron14:08:09

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?

borkdude14:08:47

The landing page has a summary of the features: https://babashka.org

borkdude14:08:51

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

shaunlebron14:08:31

which java classes are available?

shaunlebron14:08:59

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

shaunlebron14:08:03

oh okay, I needed java.lang.management.ManagementFactory

borkdude14:08:53

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

borkdude14:08:18

Probably runtime something something

shaunlebron14:08:31

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

shaunlebron14:08:30

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

borkdude15:08:03

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

borkdude15:08:38

But with a language that makes sense to Clojure devs

borkdude15:08:20

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

shaunlebron15:08:03

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

borkdude15:08:21

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

borkdude15:08:14

Sorry too distracted, have to get off the bus

borkdude16:08:39

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

borkdude16:08:13

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?

borkdude16:08:23

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

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

borkdude16:08:53

Hope that helps.

shaunlebron22:08:33

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
shaunlebron22:08:08

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

martinklepsch18:08:20

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

martinklepsch19:08:28

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

rmxm19:08:59

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 🙂

steveb8n22:08:13

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?

rmxm23:08:55

Thanks, thanks @U04V15CAJ will test.

hlship15:08:02

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

borkdude15:08:15

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

hlship15:08:48

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

hlship15:08:20

pretty was some of the earliest Clojure code I wrote.

hlship15:08:48

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
                    (sci.core/stacktrace)
                    (sci.core/format-stacktrace)))
      (println "command" command "not found - showing beef help:")
      (println "\n\nfailed (see trace before help):\n" (str (.getName (.getClass e)) ":") (ex-message e)))