tags:

views:

127

answers:

1

I've clojure running within Eclipse. I want to pass arguments to clojure when running it. In the below the arguments are available in the REPL but not in the script itself. What do I need to do such that in the below typing arg1 in the REPL will return the first argument?

Script:

(NS Test)
(def arg1 (nth *command-line-args* 0))

After clicking on the Eclipse "Run"...

Clojure 1.1.0
1:1 user=> #<Namespace test>
1:2 test=> arg1
nil
1:3 test=> *command-line-args*
("bird" "dog" "cat" "pig")
1:4 test=> (def arg2 (nth *command-line-args* 1))
#'test/arg2
1:5 test=>  arg2
"dog"
1:6 test=> 
+2  A: 

Seems like maybe your arg1 is being defined before *command-line-args* gets a value. *command-line-args* is in clojure.core, so every namespace should be able to see it (unless you define a namespace and specifically tell it to exclude core or exclude that var). I don't know how Eclipse launches a REPL or how/when it loads namespaces or user code, so I don't know the problem.

But you could turn arg1 into a function, and then it should always return the current value of *command-line-args* (since it'll be resolved at runtime, and *command-line-args* should have a value by the time you call the function).

(defn arg1 [] (nth *command-line-args* 0))

Better, if (nth *command-line-args* 0) is really that much to type itself (which I don't think it is, really) you could write a better function:

(defn ARGV [n] (nth *command-line-args* n))

Then use (ARGV 0), (ARGV 1) etc. Keep in mind that vectors are themselves functions of their arguments, so you could just as easily do (*command-line-args* n) directly (once you're sure *command-line-args* is not nil; otherwise you'll get a NullPointerException.)

Using a lot of defs to assign names to things at the top-level is usually not idiomatic in Clojure. If you want to refer to command line arguments locally and just give them a shorter name for a while, there's let:

(defn foo []
  (let [arg1 (nth *command-line-args* 0)]
    ...))

Again, this way arg1 should get its value at runtime (whenever you call foo) so it should work.

Brian Carper
Brian, thanks for the suggestions. It certainly appears to be something with the way the REPL starts in Eclipse; running the script directly works as expected.FYI, not sure why, but setting defining arg1 as a function doesn't work as I expected. The below is a new script and the output running it directly. (ns test)(println *command-line-args*)(defn arg1 [] (nth *command-line-args* 0))and running it...java -cp /Path_to_jar/clojure.jar clojure.main com.clj cat dog(cat dog)#<commie$arg1__12 commie$arg1__12@67e13e07>(println arg1)
Teflon Mac