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.