Fork me on GitHub
Rupert (All Street)08:02:29

Hi all, Please can you help advise if/how the following three code reuse scenarios would be done in babashka: • [1] "Require" a babashka script from another babashka script in a different directory. ◦ looks like is the solution ▪︎ (cp/add-classpath "other-dir")(require 'your.test-a 'your.test-b) • [2] Call a secondary bashka script multiple times from a babashka script ◦ e.g. my-babashka-script.clj calls on 5 different directories. • [3] From a babashka script, call a function in another babashka script (e.g. call file-tree in without running the file (causing it to create/print a tree).


are all the files in the same root dir? or some are in a parent or sibling dir?

Rupert (All Street)08:02:26

I guess sibling dir would be most flexible scenario.


by sibling i meant its not in a subdir but outside the parent. i think you mean they all are in the same file tree?


if yes have you tried the project setup?

Rupert (All Street)08:02:40

Thanks for the link. I don't think that helps with scenario [2] or [3]?


for 2 when you say call, you still mean require or execute?


3 can be addressed by the project setup

Rupert (All Street)08:02:30

Yes - for scenario [2] I want to do it multiple times (e.g. I have 5 directories I want to run tree.clj ). I think it will only get run once.

Rupert (All Street)08:02:54

For [3] - I want to use an existing script as a library and not trigger the side effects.


right, the 3rd one is a problem as the print is right at the top and require will cause it and no way to avoid it. id recommend to copy the functions needed and expose an fn which you require and call. that script isnt intended for requiring

Rupert (All Street)09:02:19

Sounds like a serious shame since many/most babashka scripts are written like this.


sure but this is standard clojure behaviour

Rupert (All Street)09:02:19

Yes - but most clojure scripts aren't written like that only babashka scripts are.


You can introduce a function and invoke it with bb -m your-ns/your-fn or bb -x your-ns/your-fn . If you want to have globally invokable scripts, use #C0400TZENE7


You can also use (when (= *file* (System/getProperty "babashka.file"))) (do-my-side-effects))

Rupert (All Street)09:02:49

Yup - that would make the scripts more reusable - but the examples in github and common usage don't do that. Which means that a lot of the code so far can't be re-used as a library. Good to see there is a way to do it though.


yes, they are meant for direct invocation.

Rupert (All Street)09:02:41

How about scenario [2]?


[2] : Use a function


You can also use (load-file ...) but this is less common and not recommend for a real project

Rupert (All Street)09:02:25

I'm thinking about using scripts that I don't own and don't want to change the code for.

Rupert (All Street)09:02:51

Cool - load-file seems like the way to go for that


"Scripts you don't own and don't want to change the code for" are usually libraries you include in bb.edn and call as functions

Rupert (All Street)09:02:14

I assume I can (binding[*input* ...] (load-file "") ? There's a note that it won't work Note that *input* is not available in preloads.?


I would avoid using *input* for anything else than small CLI one-liners.


There are other ways to do that stuff in scripts

Rupert (All Street)09:02:35

Nearly all Clojure code (even apps) I can reuse as libraries. However, there is an encouragement for bb scripts to be one file solutions (so the library code is often bundled into the execution code).

Rupert (All Street)09:02:50

Just hoping we don't end up with lots of bb code that we can't reuse because it executes.

Rupert (All Street)09:02:56

e.g. there are useful functions in the but none can be used without causing the file to run.


If I would want to expose tree.clj as a library I would put it in a deps.edn project and wouldn't call any top level side effects. Then I would expose a -main function that does CLI parsing and calls the library logic. You can invoke the tree functions from bb.edn tasks or you can install it as a global script with #C0400TZENE7. This covers as far as I know all major use cases.


@U7ERLH6JX Maybe this is something you could go into a little bit of detail in in the workshop

Rupert (All Street)09:02:09

This requires users to make the decision up front for their code to be reusable. Seems like the babshka should heavily encourage scripts to be reusable by default.

Rupert (All Street)09:02:37

There is a major issue in the re-frame space where there is loads of code written but very low reusability across projects/companies due to the design of the framework. It's really held clojure frontends back because so little sharing/reuse. Just concerned the default option in BB is encouraging the same outcome.


This is how it goes with all projects: you start off with little one-off hacks and if it becomes more widely useful, you make libraries. There's nothing stopping you from making your code re-usable.


also the primary intention is that these are examples, intended for inspiration not as libraries

Rupert (All Street)09:02:54

Yes for code you own - I'm thinking about BB code that is shared online. People create cool things not realising it can't easily be built on top of.


@UJVEQPAKS You can see a combination of non-reusable code + reusable code here: The .clj files themselves cause top level side effects, but they call into the re-usable libraries

Rupert (All Street)09:02:04

Yup - agree these examples are reusable.

Rupert (All Street)09:02:55

Maybe we should update the main examples with (when (= *file* (System/getProperty "babashka.file"))) (do-my-side-effects)) and promote its usage more commonly?


sounds good


the examples were written a long time ago before most of the bb.edn stuff and bbin stuff existed


If you want to contribute, feel free to make some PRs

Rupert (All Street)09:02:09

I don't have time at the mo - but will do if I get time down the line.

👍 2
Rupert (All Street)09:02:06

Thanks @U7ERLH6JX and @U04V15CAJ very much for all the help this morning. Have a good rest of your Sundays.


Hi, after some commits in 1.0.174-SNAPSHOT I noticed that

clojure.lang.ExceptionInfo: Method submit on class java.util.concurrent.ThreadPerTaskExecutor not allowed!
when I try to run virtual threads. May be I should use another branch than master?


That class isn't available on the master branch. As mentioned several times already, you should use the jdk19-loom branch, but it isn't in sync with master. You can help with merging master into that branch via a PR.


Ah, got it. Thank you.

mike_ananev17:02:28 I've merged jdk19-loom branch to master. Then I compiled and check that loom threads are available. Then, I made a PR. But you should probably check that I merged all code correctly.


Can you direct the PR at the jdk19-loom branch?


I was able to change that


We're not merging this to master yet since jdk-19 is only an experimental graalvm build which won't get updates, so we're maintaining a jdk19-loom branch which we will bring up to date with master, once in a while, until we can migrate to an lts release


I'm a skao. 🙂 I did it totally wrong. I should rebase jdk19-loom on master but not vice versa :face_palm: Should I change my pr?


You should merge master into jdk19-loom and then send a PR to update the jdk19-loom branch. But you have to leave the jdk19 specific changes intact


I think in the next graalvm release we could maybe upgrade to 20:


This will be April 18, 2023


I'll make an attempt locally to bring the branch up to date


There was one issue in jdk 19 22.3.0 - I wonder if it's fixed in 22.3.1 - if it is, we could maybe go with that one... if we can make all the tests work


ok, made it in sync with master now


The console bug seems to be solved in 22.3.1:

$ ./bb -e '(prn (System/console))'
#object[ 0x42e8df80 ""]
(with the updated jdk19-loom branch on cirrus CI)

👍 1

Also the Windows test seems to have resolved


error messages seem to have changed from jdk11 -> jdk17 though so I'll need to change some test


all tests now working in the branch:

🚀 1
👍 1

Fun way to call babashka.http-client from the command line:

bb --prn -x babashka.http-client/request --uri  --method :get

👍 1

Oooh, this is so nice. Piped into jet and it looks lovely.

👍 2