tools-deps

Discuss tools.deps.alpha, tools.build, and the clj/clojure command-line scripts! See also #depstar #clj-new
2020-10-01T05:53:33.139200Z

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?

practicalli-john 2020-10-01T08:27:38.139600Z

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

2020-10-01T16:26:37.141500Z

That seems like an unfortunate UX decision…

alexmiller 2020-10-01T13:09:34.140200Z

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

borkdude 2020-10-01T13:10:28.140600Z

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

alexmiller 2020-10-01T13:11:10.141300Z

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

2020-10-01T16:28:12.143Z

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.

alexmiller 2020-10-01T17:16:17.143400Z

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

vlaaad 2020-10-01T17:21:41.143500Z

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

alexmiller 2020-10-01T17:21:55.143700Z

-M

alexmiller 2020-10-01T17:22:04.143900Z

where future = now

vlaaad 2020-10-01T17:34:41.144600Z

Ah, I misunderstood your previous message

alexmiller 2020-10-01T17:34:43.144700Z

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.

alexmiller 2020-10-01T17:35:13.144800Z

yeah, I meant vs previous, not vs future

👍 1
2020-10-01T18:21:05.145700Z

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.

2020-10-01T18:21:47.146400Z

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…

2020-10-01T18:22:10.147100Z

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

alexmiller 2020-10-01T18:22:27.147500Z

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

2020-10-01T18:25:45.149500Z

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.

alexmiller 2020-10-01T18:30:21.150300Z

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

2020-10-01T18:30:35.150500Z

No.

alexmiller 2020-10-01T18:31:20.150700Z

ok, then what is the complaint?

2020-10-01T18:31:36.150900Z

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?

2020-10-01T18:32:03.151100Z

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
etc.

alexmiller 2020-10-01T18:37:45.151500Z

ok, thanks for the feedback

👍 1
borkdude 2020-10-01T18:38:00.152Z

> 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

borkdude 2020-10-01T18:38:56.153100Z

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

alexmiller 2020-10-01T18:38:57.153200Z

why vs running a repl?

2020-10-01T18:39:01.153400Z

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

borkdude 2020-10-01T18:40:41.154800Z

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

alexmiller 2020-10-01T18:40:45.154900Z

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

alexmiller 2020-10-01T18:41:19.155200Z

so is that -e or -m ?

borkdude 2020-10-01T18:41:49.155600Z

let me just do a zsh history thing

alexmiller 2020-10-01T18:42:14.156Z

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

borkdude 2020-10-01T18:52:17.156600Z

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

borkdude 2020-10-01T18:52:36.157Z

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

borkdude 2020-10-01T18:53:38.157700Z

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.

alexmiller 2020-10-01T18:58:32.158500Z

thanks for the data

borkdude 2020-10-01T19:03:12.159400Z

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

borkdude 2020-10-01T19:03:51.160200Z

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

seancorfield 2020-10-01T19:05:21.161300Z

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.

alexmiller 2020-10-01T19:06:33.161500Z

thx

borkdude 2020-10-01T19:07:15.161800Z

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

practicalli-john 2020-10-01T20:29:53.175100Z

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.

dpsutton 2020-10-01T20:31:45.176300Z

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])"
end
one clj-doc and the other clj-source. easy to update to -M -e though

👍 1
borkdude 2020-10-01T20:31:45.176400Z

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

borkdude 2020-10-01T20:32:47.177400Z

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 :)

2020-10-01T22:19:13.178300Z

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

lread 2020-10-01T22:20:34.179100Z

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:

😎 1
2020-10-01T22:28:52.182200Z

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:

<build>
    <plugins>
        <plugin>
            <groupId>com.theoryinpractise</groupId>
            <artifactId>clojure-maven-plugin</artifactId>
            <version>1.8.4</version>
            <extensions>true</extensions>
            <configuration>
                <sourceDirectories>
                    <sourceDirectory>src</sourceDirectory>
                </sourceDirectories>
            </configuration>
        </plugin>
    </plugins>
    <!-- How does maven use this? -->
    <sourceDirectory>src</sourceDirectory>
</build>

2020-10-01T22:33:40.183Z

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

2020-10-01T22:35:25.183400Z

Ah, that makes sense - mixed language project.