Fork me on GitHub

Apologies if this has been asked & answered before (I did search, but couldn’t find anything relevant), but in recent versions (specifically v1.10.1.697) the following occurs:

$ clj -e '(println "Hello, world")'
WARNING: When invoking clojure.main, use -M
Hello, world
I understand that this can be “fixed” with clj -M -e '(println "Hello, world")' , but is that intentional?


It seems so. The -M flag is required when invoking clojure.main.


That seems like an unfortunate UX decision…


yes, all invocations of clojure.main should now be routed through -M


even when $ clj -- -e '(+ 1 2 3)' which is quite unambigious?


it's unambiguous now but we're trying to open up arg space for repl execution


It seems to me that evaluation of a something provided on the command line should be considered at the same level of importance as running a REPL or invoking a main function, FWIW.


expression eval is done by invoking clojure.main. -M is how you (now) invoke clojure.main.


How are we going to invoke clojure.main in the future? :)


where future = now


Ah, I misunderstood your previous message


yeah, I meant vs previous, not vs future

👍 3

clj was originally built solely around clojure.main. we are in the process of making it bigger than that and this is part of segmenting off that part of the functionality.


I understand the improvements that brings to the implementation, I’m more making a comment about the (negative, imho) UX that creates, especially for newcomers.


i.e. why should a newcomer have to know that in order to evaluate an expression on the command line, they are actually invoking clojure.main? That seems like incidental complexity to me…


To non-Java/Clojure folks, clj is clojure.main.


I don't think evaluating an expression on the command line is actually a thing most people do compared to running a repl


Sure, but that doesn’t mean that CLI evaluation isn’t worth supporting in a clear and concise (and backwards compatible, though I know we’re in a period of time where that is being consciously and deliberately broken) manner.


is your complaint about the warning message mentioning clojure.main?


ok, then what is the complaint?


My complaint is why does anyone need to know they’re invoking clojure.main in order to evaluate something on the command line. Shouldn’t this be a “first class” operation, regardless of how it’s implemented under the hood?


After all that’s how most other languages handle this - Principle of Least Surprise etc. etc.

$ python -c 'print("Hello, world")'
Hello, world
$ perl -e 'print "Hello, world"'
Hello, world


ok, thanks for the feedback

👍 3

And to be clear, I don’t do this all that often, but it is a handy feature (e.g. in shell scripts).


the most common use of it that I'm aware of is to trigger deps loading without doing something else, which you can now do with -P


Sure, but -P won’t evaluate an arbitrary expression. I like to (println a specific message to make build log searching easier.


> I don't think evaluating an expression on the command line is actually a thing most people do compared to running a repl I do this all the time on the command line


-M -m -M foo.clj -M -e, don't know if I can get used it ;)


why vs running a repl?


A lot of things I do in my open source projects is testing out command line applications which are usually one shot. Yes, I also use a REPL, but actually more often I execute one time invocations


so is that -e or -m ?


let me just do a zsh history thing


(note new -P to prepare deps w/o executing, which is one prior use case for -e)


ok, I wrote this horrible script now:

#!/usr/bin/env bash

history | bb -iO '(->> *input*
                  (map #(as-> % x (str/trim x) (str/split x #"\s+") (rest x) (take 2 x)))
                  (keep #(when (and (str/starts-with? (first %) "cl") (second %) (> (count (second %)) 1)) (subs (second %) 0 2)))
                  frequencies (sort-by second >) (take 10))'
["-A" 326]
["-S" 208]
["-e" 172]
["--" 79]
["-M" 76]
["/t" 30]
["-J" 22]
["-m" 18]
["-X" 12]
["-R" 8]
which indicates I use -e way more often on the command line


but so far I haven't used -M a lot, usually -A


because instead of -m there's usually an alias for it. But with -e there isn't. So when invoking main directly, -e is my primary use case.


thanks for the data


I think clj /tmp/foo.clj is also one of my primary use cases, this is where ["/t" 30] probably comes from


but because the filenames can change, it doesn't really show well here


I just checked my history, my dot-clojure file, and my deps.edn at work and I almost never use -e without also using -m it seems. Just as a contrary data point to the above.


$ alias cljm='clojure -M'
$ cljm -e "(+ 1 2 3)"
it works


For my own brief experiences, I only every used -e once as a saw an example in the Clojure CLI docs. I am not aware of any use cases where I would want to evaluate clojure on the command line, especially if I can run the repl just as quickly. If I was going to script something with Clojure, then I'd try using Babashka, it looks great. I am fascinated as to what the scenarios could be for using the -e . If anyone has a link to examples, please let me know. The only thing I find a little strange is when running an application from the command line, eg. clojure -M -m namespace.main , from a usability point of view the -M looks a little redundant.. After thinking about this for a few days, I realize I don't actually run the application that way. I'll either run in the REPL or create a jar/uberjar and run it that way. I though about using an alias called :project/run that ran the unpackaged project, which I could include in a project template (eg. for clj-new), but not sure how valuable that would be. I find the -X flag more appealing (and more Clojurey) approach, as I've been writing command line -main functions to take hash-map as an argument for a while now. It seems an idiomatic approach to have all entry point functions in a project take a hash-map where possible.


in fish i have these handy shell functions

function clj-doc --description 'Get the docstring of a function'
clj -e "(require 'clojure.repl)(clojure.repl/doc $argv[1])"
one clj-doc and the other clj-source. easy to update to -M -e though

👍 3

Well, sometimes I use -e to require some namespace or a compile invocation for example


No big deal, can be easily hidden in a script, Makefile or whatever, I just don't find -M -m aesthetically pleasing, which may not be an important argument. Whatever :)


For what it is worth, I am updating rewrite-cljc to use the new cli syntax, and updating from -A -m to -M -m is not causing me any terrible discomfort. simple_smile

😎 3

Out of curiosity, what is the purpose of the sourceDirectory tag addition in the pom target? I don't see where it is used by other mvn tasks and the clojure-maven-plugin puts the same data into its own config (which I realize is unrelated to tools.deps, but it's the only mvn plugin I can think of that is directly related to building Clojure). For example:

    <!-- How does maven use this? -->


Pretty sure Maven uses that to know where to go to build Java source. IOW it’s probably not relevant for a deployed artifact.


Ah, that makes sense - mixed language project.