https://github.com/clojure/tools.cli 1.4.256 -- Tools for working with command line arguments.
• https://ask.clojure.org/index.php/14977/tools-cli-capture-unrecognized-options-unparsed-arguments: add :subcommand :explicit and :subcommand :implicit options. The former replaces :in-order true (which is deprecated) and the latter expands that parsing to treat an unknown option as starting a new subcommand.
Am I the only one who struggles with CLI libraries? I always seem to end up fighting the library's abstractions until I eventually give up and just write a loop/recur to parse *command-line-args* myself.
tools.cli follows https://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html but perhaps if you can articulate what you need that isn't the GNU Program Argument Syntax Conventions, folks might be able to point you at a suitable library?
I need to express devops workflows in the command line and they look like this: bb <task> <step|cmd>+ -- <cmd>
Examples: bb walter delete create delete or bb ansible git-check render lock exec git-push unlock-any -- ansible-playbook main.yml or bb tofu render tofu:init tofu:apply:-auto-approve.
The first example is the lifecycle of a package called walter. The second example is running ansible with a client side lock. The third example is running multiple commands of tofu to create infrastructure.
After fighting with babashka/cli, I decided to implement this DSL with loop/recur. The https://github.com/amiorin/big-config/blob/86ff81aa7c6e90728e1b62f623fcca6a1418e1cb/src/clj/big_config/workflow.clj#L338-L379 solution that I developed.
Ah, yeah, those don't follow the GNU conventions so you might as well do your own custom parsing at that point. Might be worth your while discussing in #babashka around bb tasks and see if anyone there has suggestions beyond "roll your own"...
https://github.com/replikativ/beichte/ 0.2.6 — Effect analysis for Clojure compiler pipelines
beichte infers effect levels for Clojure expressions and vars, useful for compiler builders who need to know what code is safe to transform (AD, GPU, SIMD, CSE, parallelization).
Four-level effect lattice: :pure < :local < :mutation < :io
Feature flags: :throws, :random, :reflects, :allocates
Pre-annotated registry: ~300 clojure.core vars + common Java methods out of the box
Compilation target budgets: ask "is this code compilable for GPU?" and get a yes/no answer
Source-level analysis: recursively reads .clj source from classpath, no AOT required
Explicit caching: no global mutable state — pass a context for compiler pipelines, get fresh analysis in the REPL
(require '[beichte.core :as b])
(b/analyze '(+ 1 2)) ;=> :pure
(b/analyze '(println "hi")) ;=> :io
(b/analyze '(swap! a inc)) ;=> :mutation
(b/compilable? :gpu '(+ 1 2)) ;=> true
(b/compilable? :gpu '(println "hi")) ;=> false
(b/compilable? :ad '(Math/sin x)) ;=> true
;; Explicit context for cross-call caching in compiler passes
(let [ctx (b/make-context)]
(b/analyze-var #'my-fn ctx)
(b/analyze-var #'other-fn ctx))
Built on tools.analyzer.jvm. Apache 2.0.
clojars org.replikativ/beichte
https://github.com/replikativ/beichteyou are on fire
Damn I always wanted to build this, excellent work, thank you! This solves another problem for compiler writers: answering the question which expressions can be inlined and evaluated at compile time. Excellent
i wonder if this is generalizable to a "type" system?
This is an effect type system An effect type orthogonal to the underlying value
i meant reusing the analysis engine, but i won't distract further in this thread
I use it with typedclojure in my compiler to compile to GPUs/accelerators. Hopefully I can release it soon, releasing beichte was a step to get it out. In general I think Clojure should grow more of a PL/compiler infrastructure that makes it easier to bend the language to different domains. A bit what Racket has, but more pragmatic and flexible.
Also I think optional/gradual types have proven to be very potent (Python is so much more clean with it, TypeScript as well), I think Clojurians should appreciate them more and provide optional type annotations to their functions at least for important libraries. It would help a lot to apply more complex compilation/verification techniques, without taking away the open-ended flexibility and pragmatism of untyped Clojure. I would definitely not make Clojure itself by default dependent on any type system and keep it untyped, but rather see type systems as different ways to extend/focus its meaning. I think @ambrosebs work is really great to help that.
knowing which expressions are pure also unlocks safe partial evaluation and inlining, then it's possible to write an optimizing compiler 🙂
Correct 🙂. I did this excessively in https://github.com/plai-group/daphne. It would also be possible to do this in a GraalVM implementation of Clojure and get a lot more out of JIT.
What would you like to apply it to?
I get personally offended whenever someone says Clojure is slow, so I have a dream of building an optimizing compiler for final artifacts (e.g. uberjars) to squeeze the most possible out of it
@borkdude one idea I have is to use it to auto-lift functions out of sci sandboxes into Clojure if they are pure. This might require a bit more thought, but it could be fairly effective to minimize sandbox overhead even for heavy compute.
@whilo I wonder if Beichte could in theory be used to restrict certain effects in addition to just analysing them? E.g to throw an error when a function annotated as pure isn't actually pure
Yes, you can definitely do this. How would you want to integrate beichte?