Fork me on GitHub

clojure -A:foo and clojure -M:foo without main-opts do the same thing: invoke a REPL with alias foo merged in -- right? Should -M:foo give a warning when you forget to supply main-opts in deps.edn maybe?


or should -A not invoke a REPL since that's a clojure main invocation?


-A is for REPL invocation, according to the docs.


so -A and -M overlap there I guess


I suspect that's a bit of a grey area given that :main-opts ["-r"] works to run a REPL, yes?


well, I invoked an alias with -M while I forgot to provide :main-opts in deps.edn, so it invoked a REPL for me


that's what prompted these maybe too far fetched thoughts


Yeah, I would sort of expect -M to at least give a warning if no :main-opts are provided. @alexmiller?


(! 651)-> fgrep :repl deps.edn 
  :repl {:main-opts ["-r"]}
(! 652)-> clj -M:repl
Clojure 1.10.1
user=> ^D
(! 653)-> clj -A:repl
WARNING: Use of :main-opts with -A is deprecated. Use -M instead.
Clojure 1.10.1
user=> ^D


(so, yeah, you can specify -r explicitly as a :main-opts item)


And the corollary:

(! 656)-> fgrep :dummy deps.edn 
  :dummy {}
(! 657)-> clj -M:dummy
Clojure 1.10.1
user=> ^D
(! 658)-> clj -A:dummy
Clojure 1.10.1
user=> ^D

Alex Miller (Clojure team)21:10:20

you can supply main-opts on the command line, so -M does necessarily have to have :main-opts

Alex Miller (Clojure team)21:10:56

clj -M:my-alias-with-just-deps -m my.ns


Yes, but that's not the case we're discussing here.


See the two console examples I pasted. No command-line main-opts there.

Alex Miller (Clojure team)21:10:56

-M invokes clojure.main. clojure.main does not require opts.


Fair enough. The "implicit" -r option šŸ™‚


Why draw the distinction in the docs then that -A is for REPL execution?


because -M might not invoke a REPL when main-opts are given

Alex Miller (Clojure team)21:10:45

really, it can be used to supply aliases for anything but it's only useful with REPL (because -M can be used for main and -X can be used for functions)

Alex Miller (Clojure team)21:10:18

(and for allowing legacy stuff to continue working)


I guess this will become less confusing once -A stops executing :main-opts


I'm curious how you plan to distinguish between -A for a REPL and -M executing clojure.main which might pick up other main opts?

Alex Miller (Clojure team)21:10:07

what do I need to distinguish?


I mean: how is -A going to start a REPL without running clojure.main?

Alex Miller (Clojure team)21:10:43

it invokes clojure.main

Alex Miller (Clojure team)21:10:47

that's an implementation detail

Alex Miller (Clojure team)21:10:28

clj without -M or -X will start a repl, you let me figure out how to do that :)


So, in the absence of :main-opts in an alias, both -A and -M will work identically, always? i.e., they will both run clojure.main and they will both start a REPL?


I would maybe prefer -M to trigger a warning when there is no :main-opts [] when you want to explicitly pass 0 arguments to main (i.e. invoke a REPL)


@borkdude I don't think that is going in the right direction...


It seems that the only way to avoid continued confusion is to have clojure.main without arguments not start a REPL -- and require -r for that? šŸ™‚


So, in the absence of :main-opts in an alias, both -A and -M will work identically, always? i.e., they will both run clojure.main and they will both start a REPL?


I guess you could always have a new entry point for a REPL and have -A invoke that...?

Alex Miller (Clojure team)21:10:16

I don't understand what problem is bothering you


(or rather "have the absence of -M and -X invoke that")

Alex Miller (Clojure team)21:10:41

the absence of -M or -X means: invoke a repl

Alex Miller (Clojure team)21:10:09

in other words, the default behavior of clj is: invoke a repl


(! 659)-> clj -A:dummy -r
WARNING: When invoking clojure.main, use -M
Clojure 1.10.1
user=> ^D

Alex Miller (Clojure team)21:10:53

ok, you're outside the bounds of documented behavior


-r is a documented main-opt that causes clojure.main to start a REPL, isn't it?

Alex Miller (Clojure team)21:10:46

yes, but when we stop accepting main opts outside of -M, that's no longer a thing

Alex Miller (Clojure team)21:10:10

there may be some other set of accepted arguments in the repl case that have nothing to do with clojure.main


OK, so there will need to be a change in the behavior of clojure.main at some point to "fix" this?


clojure.main's help says

-r, --repl          Run a repl

Alex Miller (Clojure team)21:10:29

"clj starting a repl" is distinct from clojure.main

Alex Miller (Clojure team)21:10:01

yes, the mechanism clj currently uses to start a repl is clojure.main

Alex Miller (Clojure team)21:10:07

but that's an implementation detail


So there will be a non-`clojure.main` entry point that clj can use to start a REPL?


(otherwise this confusion is going to continue)

Alex Miller (Clojure team)21:10:05

what I'm saying is - I am promising clj will start a repl. the end.

Alex Miller (Clojure team)21:10:34

and I'm promising that clj -M will run clojure.main

Alex Miller (Clojure team)21:10:55

and that clj -X will invoke a function with a map


but you're not promising that clojure.main will not support -r at some future point :rolling_on_the_floor_laughing:

Alex Miller (Clojure team)21:10:32

there are no plans to make clojure.main do anything different than what it does now

Alex Miller (Clojure team)21:10:52

in the before times, clj always ran clojure.main. that is no longer the model

Alex Miller (Clojure team)21:10:22

the new model is: ā€¢ by default, run a repl ā€¢ with -M, run clojure.main ā€¢ with -X, execute a function with a map

Alex Miller (Clojure team)21:10:40

and "run a repl" does not say anything about clojure.main

Alex Miller (Clojure team)21:10:29

if you want to explicitly run clojure.main to run a repl, then clj -M or clj -M -r will do that


The confusion arises because the docs talk about "using -A (for REPL invocation)" when it still runs :main-opts!

Alex Miller (Clojure team)21:10:17

well, we're in a bridge period between the two models


The sooner -A stops running :main-opts the better...


(mind you, even in that future world, I think @borkdudeā€™s confusion will still be present, yes?)

Alex Miller (Clojure team)21:10:40

if the confusion is that you can use clojure.main to run a repl, then yes

Alex Miller (Clojure team)21:10:40

but it's easy to reason about if we are properly conveying that -M == run clojure.main


Argh, I'm being bitten by caching here šŸ˜ž


(! 665)-> clj -Sforce -A
Missing required argument for "-A ALIASES"
(! 666)-> clj -Sforce -A -r
Missing required argument for "-A ALIASES"


^ That makes more sense.


-M and -X can be invoked without an alias, -A cannot.

Alex Miller (Clojure team)21:10:49

what does that have to do with caching? -A always requires an alias


Because this happened before I added -Sforce:

(! 662)-> clj -A
Clojure 1.10.1
(! 663)-> clj -A -r
WARNING: When invoking clojure.main, use -M
Clojure 1.10.1
user=> ^D


(note the command history numbers there!)

Alex Miller (Clojure team)21:10:10

oh, well that's just a bug then


Here's the repro for that bug:

(! 674)-> clj -Sforce -A
Missing required argument for "-A ALIASES"
(! 675)-> clj -A
Clojure 1.10.1


So the point earlier was: invoking -M with an alias that doesn't have :main-opts assumes that :main-opts is implicitly []. My question was: should this be less implicit, to avoid people ending up in a REPL when invoking -M with an alias that wasn't intended for -M at all

Alex Miller (Clojure team)21:10:16

no, because :main-opts is not required


@borkdude in the following :test has no :main-opts -- which of these would you expect to get warnings on and why?

(! 676)-> clj -Sforce -M:test -r
Clojure 1.10.1
user=> ^D
(! 677)-> clj -Sforce -A:test -r
WARNING: When invoking clojure.main, use -M
Clojure 1.10.1
user=> ^D
(! 678)-> clj -Sforce -M:test 
Clojure 1.10.1
user=> ^D
(! 679)-> clj -Sforce -A:test 
Clojure 1.10.1
user=> ^D

Alex Miller (Clojure team)21:10:20

we could do something like - if you supplied -M but did not supply either :main-opts or main-opts on the command line, then either warn or error at that point

Alex Miller (Clojure team)21:10:51

but honestly that's difficult to check right now due to where that knowledge of different parts of that is


yes, that's exactly the case I was referring to


So -M wouldn't silently start a REPL unless you said -M -r ? I think that would be reasonable.


(if it could be checked)

Alex Miller (Clojure team)21:10:23

and then -M means run clojure.main except for this one case where it fails


yeah, I guess it's not worth changing


(I'd be against an error there but I think a warning to remind folks might be worthwhile)


main opts can be supplied on the command line, so not providing arguments means the same as :main-opts [], but you can also do that with -A which is the preferred way of invoking a REPL maybe

Alex Miller (Clojure team)22:10:11

@seancorfield if you want to check the -A thing


But I suspect there's no point trying to second-guess what folks will find confusing until after we have a CLI version where -A no longer uses :main-opts


@alexmiller Thanks for the swift fix!


(! 680)-> clj -Sforce -A
-A requires an alias
(! 681)-> clj -A
-A requires an alias
confirmed fixed!

Alex Miller (Clojure team)22:10:13

I did not take the time to try on Windows, but it might already catch this case due to the different parsing. I'll check that before we get to a stable release

Alex Miller (Clojure team)22:10:46

I'm shutting down, have a good Halloween weekend y'all