This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-06-15
Channels
- # announcements (11)
- # aws (5)
- # babashka (69)
- # beginners (138)
- # calva (5)
- # cider (11)
- # cljsrn (3)
- # clojure (86)
- # clojure-europe (8)
- # clojure-italy (2)
- # clojure-nl (5)
- # clojure-norway (13)
- # clojure-uk (21)
- # clojurescript (13)
- # conjure (58)
- # core-typed (2)
- # data-science (2)
- # datomic (5)
- # degree9 (4)
- # emotion-cljs (4)
- # figwheel-main (8)
- # fulcro (29)
- # graalvm (70)
- # interop (2)
- # joker (1)
- # lein-figwheel (2)
- # leiningen (13)
- # liberator (4)
- # off-topic (21)
- # pedestal (2)
- # re-frame (10)
- # shadow-cljs (42)
- # spacemacs (29)
- # spire (1)
- # tools-deps (11)
- # vim (26)
- # xtdb (5)
@nate Talking about binary formats... cheshire also supports JSON smile, which is a compact binary encoding of JSON
$ bb '(json/generate-smile {:foo "bar" :baz 5})'
#object["[B" 0x2cc3e974 "[B@1152c8108"]
Is there a pattern people are using that provides behavior similar to python’s __name__ == __main__
? I’d like to provide a main entry point in the script but still be able to source entire files in my editor without firing main.
@grzm yeah, there is a System property you can read to determine if bb was called with a --main
arg: (System/getProperty "babashka.main")
. If that's not set, you can do (apply -main *command-line-args*)
for small scripts without a main, I've been doing this:
(defn say-hello
[n]
(println "Hello" n))
(when-not (System/getenv "DEV")
(say-hello (first *command-line-args*)))
and then I start bb's nrepl server like this: DEV=1 bb --nrepl-server
and I can eval the entire namespace without worry@nate That sounds like it might be more along the lines I’m looking for. I was hoping to use this in conjunction with a #!
, so as to not call it with bb directly, but it looks like babashka.main
isn’t set in that case (e.g., calling ./my-wonderful-bb-script
rather than bb '(my-wonderful-bb-script/-main)'
@grzm I'm not entirely sure now what you're trying to do. But *file*
might also be of help: it contains the name of the file that's currently being evaluated
cat some-script
#!/usr/bin/env bb
(ns com.grzm.some-script
(:require [clojure.pprint :as pprint]))
(defn -main [& args]
(prn "lookee!"))
(when *file*
(apply -main *command-line-args*))
@borkdude^ Thanks! That works. When I run load-file in Cider, *file*
isn’t set, so -main
doesn’t run. When called from the command line, it is.
the (when *file* ,,,)
trick doesn't work for me when using bb --nrepl-server
, still evals
I'm not sure if this defined or undefined behavior though. Maybe babashka should also have a babashka.file
property which contains the filename of --file
Thinking out loud, would it make sense for --nrepl-server
to set a babashka.nrepl-server
property?
@borkdude Is it clear what I’m trying to accomplish? I’m not sure if I’ve explained it well enough. Often I find I’m tackling something from the wrong direction, which is fine, but my explanations leave people wondering “what on earth is he trying to do?”
@grzm Well, for the script you are writing there I would expect you to invoke it with -cp
+ -main
or --file
/shebang. The property babashka.main
is used to distinguish between those two cases
it actually can't see that, because the shell calls the binary with the file argument for you
I’d rather not have people worry about which interpreter they’re using: ruby, or perl, or bash, or whatever, so I’d rather not have to call bb some-script
, if I’m understanding correctly. I could wrap everything in some separate bash script that calls bb some-script
, but that’s just extra wrapping.
@nate’s System/getenv
is workable and robust, so I’ll lean on that for now. Having all the args potentially available would work, too, and I wouldn’t have to remember to set the right environment variable, 🙂
@grzm I think I might have a solution, but I first want to have your problem straight. You want to execute using a shebang. In that case, the -main function should be executed. Else it should not?
Yup. In the some-script
example above, I want (apply -main *command-line-args*)
to execute when ./some-script
is called from the command line. When I load-file
file from the repl, I don’t want (apply -main *command-line-args*)
to be called.
in normal clojure I would just solve that with multiple entrypoint script. script1
contains some functions. script2
load-files script1
and calls the function. you tell the end user to call script2.
Right now, yes. I haven’t had a need to dynamically call load-file. (To be really explicit, I’m calling cider-load-buffer
, which I believe calls load-file
)
Yeah, that’s how I’d do it in normal clojure, too. But that’s not how I’d do it when I’m writing scripts, which I wouldn’t use Clojure for, generally.
the use case you are describing doesn't correspond to the __name__ == __main__
python example I think?
or maybe it does, in the case you load the file from some other file, name__ would not be equal to main__, but if you invoke it directly, it would?
My understanding is that people use it as a guard to be able to use the file as a library and as a main entry point, using if __name__ == __main__
for the main entry point. I agree it’s not exactly the same.
in that case (System/getProperty "babashka.file")
might make sense, so you can do:
(= (System/getProperty "babashka.file") *file*)
*file*
contains the canonical path of the currently executing file. we could make babashka.file
also have the canonical file path of the -f
argument (or shebang)
so when you load-file
from some other file, babashka.file
surely isn't the same as *file*
I think that sounds reasonable, and as far as I’ve seen, *file*
is nil
when I’m running cider-load-buffer
. However, @nate reported that didn’t work for him.
*file*
should contain the canonical file path when using load-file
. you can very easily try this out yourself
this is the implementation:
(let [f (io/file f)
s (slurp f)]
(sci/with-bindings {sci/ns @sci/ns
sci/file (.getCanonicalPath f)}
(sci/eval-string* sci-ctx s)))
okay, let me be clear: I’m calling cider-load-buffer
. I assumed (it looks like wrongly) that it’s calling load-file
.
you can check what the babashka nrepl server receives when starting it with BABASHKA_DEV=true bb --nrepl-server
you can then see if it contains a giant eval
op with the entire buffer or a load-string
with a filename
Is there a way to read the version of the babashka binary? I can think of shelling out (--version), but it would be nicer without starting a new process
The reason I want to use it is checking if the user has a babashka installation that supports the features being used. With all the additions this might save some time in debugging users issues
E.g. typical usecase (in my mind): at some point in time I build a script with the latest babashka. I would set the minimal babashka version to that babashka version. I’m assuming it will work with all newer versions, but not necessarily with older ones. I can see how this will save myself some headaches
not yet, so I'll add babashka.main-file
(or some other name?) which contains the -f
argument and babashka.version
which contains the version as system properties?
Clojure uses *file*
. I don’t have a strong opinion about the name
And clojure has *clojure-version*
I guess it makes sense to not copy that, but make that *babashka-version*
. A use case for clojure I have seen is this one https://github.com/tonsky/clojure-future-spec/blob/master/src/clojure/future.clj#L3
babashka already has *file*
. this has a different meaning (see the above discussion)
I won't introduce any non-clojure public vars into the core namespace for compatibility. I was proposing system properties
Ah ok. I don’t need *file*
yet so I haven’t thought about that yet
Yeah system properties sound good
Ah ok now I see what you said
sounds good
I didn’t read the above discussion about *file*
🙈 It was a coincidence I guess 🙂
it's in the air. sometimes I don't hear something about clj-kondo for a while and then one day there are like 5 issues or questions within a few hours
or some library or new babashka feature was just introduced and a new user asks the next day if that is supported.. 🙂
Maybe everyone is leveling up their usage of Babashka around the same time 🙂
I don’t want to create Graalvm projects anymore for tooling. I just want to use Babashka now and expect of people that they have a babashka binary installed
So to summarize: name__ = "main__" pattern: https://github.com/borkdude/babashka/issues/478 And one property for the version: https://github.com/borkdude/babashka/issues/479