On Apr 18, 2009, at 5:24 AM, Meikel Brandmeyer wrote:
Ok. You asked for it, so I will play the devil's advocate! Why this fixing on one somehow blessed function? When the namespace is loaded I can call any public function directly. Why do I need (run ...)? I don't see the value of this, since run should probably return a numeric exit code, no? While any other function will provide eg. a map or a seq, which is probably much more useful.
From within Clojure you can call any function you like. The purpose of this function is to bridge the gap between the shell and Clojure while still being reasonably callable from within Clojure. At the command line all we have for arguments are strings and all we can return is integer status.
The purpose of marking a function as "the one to call when invoking the script" is to allow clojure.main to call the namespace as a program by naming only the namespace. The purpose of making it a standard interface (strings in, integer status out, use streams for anything else) is that we can call it that way easily from either the command line or from within Clojure. It's an interface that's been tried and true for many years in Unix tools and in Java's "public static void main (String[] args)" (modulo the return code issue being different between the two.
Let me bring scsh into the discussion and show how they handle this issue. They have a command line switch to tell the scsh driver which function to invoke after loading the script. This could also be done for clojure.main: java -cp .. clojure.main -E my.ns/main my-script-defining-my-ns.clj
I'm trying to make this kind of command line easier to use and explain. We basically already have what you're proposing:
java -cp .. clojure.main -i my-script-defining-my-ns.clj -e "(my.ns/ main *command-line-args*)"
Contrast that to what I'm proposing: java -cp .. clojure.main my.nsI still like mine, but an alternative of specifying the function directly and then calling it with the rest of the args as strings and returning the int it returns would also be succinct and perhaps even clearer:
java -cp .. clojure.main my.ns/main
The script does not need to be in the Classpath. As soon as it is loaded the namespace is available. (Which brings me to the double book-keeping of require...)
I'd rather have it in classpath. What is the "double book-keeping of require..."
The script could be made self-contained using hashdot: #! /usr/bin/env hashdot ;;.hashdot.main = clojure.main ;;.hashdot.args.pre = -E my-ns/main (ns my.ns) (defn main [& args] ...) ./my-script-defining-my-ns.clj With this approach I can also choose different entry points for different invokations of the same script. Although I'm not sure this is an interesting feature.
I'm not sure it's interesting either, but the idea of invoking a Clojure *function* as a "program" rather than a Clojure namespace or file is a good one I think.
Just some thoughts to a look a different approach.
Thanks very much. --Steve
smime.p7s
Description: S/MIME cryptographic signature