New prerelease of Clojure CLI 1.10.3.875:
• New: support for specifying multiple functions with -X with ->
semantics
• https://clojure.atlassian.net/browse/TDEPS-182 - Improve deprecation message to be more accurate
• https://clojure.atlassian.net/browse/TDEPS-183 - Fix -Sdescribe output to be valid edn on Windows
• https://clojure.atlassian.net/browse/TDEPS-179 - Fix incorrect classpath when :classpath-overrides removes path
Awesome! Can you point me to an example of how that new -X
stuff works? Is it literally just -X:myalias foo.bar/fn1 foo.bar/fn2 some.other/thing
and each should take a hash map and return a hash map?
yes
What happens if any of them return nil
? Does exec just pass the original input hash map into the next function, or does it end up passing nil
?
well importantly, the first function gets the kvs from the exec-args/ cli
it's like ->, so if one function returns nil, the next gets nil
Ah, so that also means that the functions in the 2nd pos on don’t need to take hash maps, right? It could be any data produced from the earlier fns?
I suppose :)
I will not claim that this is fully baked yet, so I reserve the right to change my answer before it becomes a stable release :)
(I’m already imagining how folks like @borkdude might think of abusing this 🙂 )
evil chuckle
that seems really interesting
with low startup time that makes bash very close to a useable repl
repls are also very usable repls :)
haha very true 🙂
> -X:myalias foo.bar/fn1 foo.bar/fn2 some.other/thing
how does it know that it's (-> {} foo.bar/fn1 foo.bar/fn2 some.other/thing)
and not (foo.bar/fn1 {'foo.bar/fn2 'some.other/thing})
?
@seancorfield could you help me understand how I could abuse this? ;)
symbols at the front are functions
and @dpsutton about startup time: how does this solve startup time?
fn* [kpath v]* map?
i was thinking about sci/bb but at that point you could just pass in forms to be evaled
ah, so clj-exec first consumes all symbol args as fn chain, and then rest args as map arg?
well we now have trailing map support ala 1.11 too
> fn* [kpath v]* map?
this is great explanation 😄
https://github.com/clojure/brew-install/blob/1.10.3/src/main/clojure/clojure/run/exec.clj#L100
to be more precise
parsing is done with that spec
Just tried it out on pwsh, it works
but of course :)
not sure how I feel about the -X threading
thanks :)
I tried this:
clj -X clojure.core/pr-str clojure.core/read-string clojure.pprint/pprint :a 1
but when I was playing with it I felt the order is somewhat hard to follow, because arg-map is in the end, unlike in real ->
(defmacro <- [,,,],,,)
:grinning_face_with_one_large_and_one_small_eye:
interested in feedback, so do more , and come back
intuitively I wanted to write this:
clj -X clojure.pprint/pprint clojure.core/read-string clojure.core/pr-str :a 1
because arg-map is closer to fn that will receive it. e.g.
(clojure.pprint/pprint (clojure.core/read-string (clojure.core/pr-str {:a 1})))
I don't know that this is something you're going to want to use all the time, but it is another dimension of composition available
the goal is not to replicate the repl. if you want that, use a repl
mm yeah...
I guess my big test is going to be breaking depstar
up into multiple -X
-compatible functions so you can run parts of it or all of it in a pipeline 🙂
if you do do that, I would be very interested in hearing your questions/feedback. if I may be so bold, that might be a better thing to do in design space before actually cutting the code :)
Okay, another argument why (fn1 (fn2 argmap))
might make sense:
PS C:\Users\Vlaaad\Projects\deps-test\lib> Get-Content .\deps.edn
{:aliases {:deploy {:ns-default deploy}}}
PS C:\Users\Vlaaad\Projects\deps-test\lib> Get-Content .\src\deploy.clj
(ns deploy)
(defn dev [args]
(merge
{:env :dev
:url "dev-cluster"}
args))
(defn prod [args]
(merge
{:env :prod
:url "prod-cluster"}
args))
(defn deploy [env]
(prn :deploy env))
Suppose I want to deploy my app. Currently I have to use this order: dev deploy
PS C:\Users\Vlaaad\Projects\deps-test\lib> clj -X:deploy dev deploy :a 1
:deploy {:env :dev, :url "dev-cluster", :a 1}
But this is unintuitive, as I would expect the at the command line first specify an "action" and then "env"
PS C:\Users\Vlaaad\Projects\deps-test\lib> clj -X:deploy deploy dev :a 1
:deploy {:a 1}
but with ->
style the main action goes last instead of being firstOh, definitely. I need to tease apart the various useful processes that depstar
performs and figure out exactly what inputs and outputs each of them have.
I have smaller things to test it on before that 🙂
I don’t understand this at all. ->
says “do things in this order” and that’s exactly what I would expect: setup the env, run the command.
the key thing is that inputs/outputs need to align, which harkens to namespaced keys ... but those fight with conciseness of what you want at the CLI
agreed, the order is the most important thing here
so it's more like clj -X:build clean jar
than clj -X:build deploy dev
?
yes
clojure -X:depstar sync-pom compile jar
for example 🙂
mm yeah, that makes a lot of sense
@alexmiller What’s the thinking around -X
functions that would require (shutdown-agents)
calls at the end to avoid the 60 second “hang”? That’s been a long-standing issue with -main
functions. I didn’t check the latest exec source but does it handle that? (since you clearly cannot chain exec functions that call shutdown-agents
)
Haven’t thought about it
I just looked at the exec.clj
code and it does not call (*exit* 0)
or (shutdown-agents)
in the “happy” case…
Yeah, my first test of chaining tasks leads to a 60 second hang at the end because of that.
(I used to run the tasks individually and they had calls to (shutdown-agents)
at the end — which I removed so I could chain them — and I can’t just call clojure.core/shutdown-agents
via -X
because it takes no arguments 😞