I opened a Jira enhancement: https://dev.clojure.org/jira/browse/CLJ-2185
Hope I did a good job at it. On Wednesday, 21 June 2017 18:58:26 UTC-7, Alex Miller wrote: > > Was just musing some more - the Clojure Java API was added pretty late > (~1.6 or 1.7). I wonder if > > 1) changing the Java Clojure API to ensure a certain binding context and > 2) changing the main() method to invoke the Clojure function through the > Java Clojure API > > would be a good end game. Would need a lot more analysis. > > On Wednesday, June 21, 2017 at 8:52:48 PM UTC-5, Alex Miller wrote: >> >> >> >> On Wednesday, June 21, 2017 at 6:09:43 PM UTC-5, Didier wrote: >>> >>> Great breakdown. >>> >>> 1. "compile and bootstrap yourself through gen-class" means: you >>>> generate a class and then invoke the main() method of that class >>>> >>> >>> I'd go further then just calling main. So I mean you generate a class, >>> and every function call from Java using the generated class should be >>> executed as if it were executed through clojure.main, so with the bindings >>> set and inside the user namespace. >>> >> >> I do not think you should treat clojure.main as the gold standard. >> clojure.main is a helper program and it makes some choices that may or may >> not be what every program wants. There is nothing special about the "user" >> namespace for example. Other repls choose other things (pretty sure the >> boot repl uses boot.user example). Likewise, there's nothing special about >> the set of things clojure.main chooses to bind on startup - lein, boot, and >> other tools make different choices. If anything, I'd say #2 is what you >> should consider the most canonical case. >> >> >>> >>> >>>> 2. "loaded at runtime" means: you (presumably) start the REPL, load a >>>> namespace (either from a source file or a class file), then invoke the >>>> -main function >>>> >>> >>> Correct. It's the case of a non AOT compiled namespace being loaded from >>> one of the many (load) functions of Clojure. Such as: >>> >>> (load "dda/main") >>> (dda.main/-main) >>> >>> >>>> 3. "bootstrapped through clojure.main" means: you invoke clojure.main >>>> (a compiled program provided with Clojure) with the -m arg specifying a >>>> namespace. This will start the Clojure runtime, load the namespace, then >>>> invoke the -main function >>>> >>> >>> Correct. >>> >>> >>>> 4. "bootstrapped through lein" means: I assume this is "lein run" with >>>> a :main set or "lein run -m" but I think lein supports specifying a >>>> namespace or a function in a namespace or a class with a main() method. >>>> Depending which of those you're doing, this is like similar to either #1 >>>> or >>>> #2 and here lein is effectively doing similar work as #3. >>>> >>> >>> Correct, yes internally lein delegates to clojure.main I believe. >>> >> >> No, I don't think lein uses clojure.main at all. >> >> >>> >>> >>>> 5. There is a Clojure Java API ( >>>> http://clojure.github.io/clojure/javadoc/), but I'm not sure if you >>>> are actually referring to this or something else. Doing so would basically >>>> mean going through that API to do the same thing as #2. >>>> >>> >>> I am talking about that API. I believe it uses RT under the hood, and >>> ends up doing the same thing that #1 does. So in my test, if you did: >>> >> >> This is actually the same as #2, not #1. It's not making an interop call, >> it's invoking a var function, just like any other Clojure call. >> >>> >>> IFn require = Clojure.var("dda.main", "-main"); >>> require.invoke(); >>> >>> This will run inside "clojure.core", and will not have any of the >>> default bindings set available. >>> >>> I think if I were to restate your suggestion, I would say that a >>>> genclass-compiled main entry point should initialize the Clojure runtime >>>> and invoke the code in a binding as if it were being invoked from other >>>> Clojure code. I can see some logic in that (although that then also >>>> affects >>>> #3 and #4 as they go through this code too). >>>> >>> >>> Ya, arguably, I wonder why the clojure runtime doesn't initialize the >>> bindings and sets the namespace to 'user before delegating execution back >>> to user code. >>> >> >> Again, there is nothing special about user and I wouldn't get hung up on >> that. It does seem like it would be reasonable to set up a binding context >> for *ns* though so it's set!-able - that's the thing that's missing. >> >> >>> If it did, then every invocation of Clojure from Java would always be >>> bootstrapped in a similar way, and run under an equal context. Clojure.main >>> wouldn't need to do it anymore. >>> >>> But there might be a good reason for not doing that inside the clojure >>> runtime. In which case, it still leaves open the question of should clojure >>> invocations through a generated class, and invocations from the Clojure API >>> mimic the bootstrapping of clojure.main? >>> >> >> I would say, no. :) But it might be reasonable to mimic a Clojure >> function invocation that has a binding for *ns*. If you want to file a >> ticket, I'm happy to think about it more. >> >> >>> >>> P.S.: I also know that in practice, this has not caused that many >>> issues, due to the fact that Clojure is now many years old, and I've never >>> heard of other people complain about the discrepancies between generated >>> classes and the clojure API versus clojure.main. So I don't think its a >>> pressing issue, but I still feel it could be worth a thought. >>> >>>> -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.