0

I'd like to create Clojure class that can be run both via main method and as a script. I need no command line arguments in both cases. Currently, I have something like this:

(ns my-namespace.core
  (:gen-class))

(defn -main
  [& args]
  (println "Hi"))

; I'd like to have something like (when (in-script?) (-main))
(-main)

In this form it is runnable as script but running it as a class shows Hi twice, not surprisingly.

I expected to find some way to distinguish runs similar to Python's idiom if __name__ == "__main__":. But I've only found old discussion mentioning this. Unfortunately, approach with *command-line-args* described there seems to be not working. I have it nil regardless of running as class or as script.

So is there a way to find out in runtime if Clojure file is running as a script or via main method?

Rorick
  • 8,857
  • 3
  • 32
  • 37

2 Answers2

2

I would suggest to just create a script.clj ns that just has the call to core/-main

DanLebrero
  • 8,545
  • 1
  • 29
  • 30
1

The short answer is no.

Clojure has exactly one, and only one way to compile and run code. There is no difference in how the program is loaded if you run it from your REPL or if you run it without connecting a REPL. Clojure is strictly a compiled language though you can, when starting it from the REPL, choose to start at a function other than main or pass main a different argument if you would like it to be different.

I have a function in my main work project called dev that I run in these cases (dev is shorter than main ;). It would also be possible to check for the presence of an nrepl connection in your program when main starts, though this is getting away from normal Clojure practices.

As food for thought, consider that you can just as easily connect the REPL to a program after it has been running for two days, than to connect the REPL before main starts.

Arthur Ulfeldt
  • 90,827
  • 27
  • 201
  • 284
  • Maybe, I needed to put it other way. My code generally need not to be packed in classes, but I refer it from test and I need to load only `def`s and not execute any stdout/stdin communications. And I need to have single source file. Consider it a homework) Any ideas? – Rorick Feb 09 '16 at 23:37
  • You can just put a call to your "main" function at the top level, call it my-main. then make the actual main function completely blank. this will cause `my-main` to run when the namespace is loaded (the step before when main is started) and then later when main is started that "main" will do nothing because the program is already running. – Arthur Ulfeldt Feb 10 '16 at 00:54