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

I 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

Attachment: smime.p7s
Description: S/MIME cryptographic signature

Reply via email to