4
votes

I'm trying to understand the -main and its namespace settings. The default namespace in a -main function seems to be "user", but function defined "above" the main function, in the same file, can be called. Are they referred? I was running this to find out:

(ns ack.doodle)

(defn fo [] "bar")

(defn -main [& args]
  (println (fo))                               ;; bar
  (println *ns*)                               ;; #<Namespace user>
  (println (get (ns-refers *ns*) 'sorted-map)) ;; #'clojure.core/sorted-map
  (println (get (ns-refers *ns*) 'fo))         ;; nil
  (println (get (ns-map *ns*) 'fo))            ;; nil
  (println (get (ns-publics *ns*) 'fo))        ;; nil
  (println (get (ns-interns *ns*) 'fo))        ;; nil
  (println (get (ns-aliases *ns*) 'fo))        ;; nil
  (println (ns-resolve *ns* 'fo)))             ;; nil

The call (fo) succeeds, yet apparently the symbol 'fo is not known in the current namespace *ns*. What's going on?

This problem hit me when trying to pass the name of some function, along with some arguments, as command line arguments to -main.

steps to reproduce

  • paste above code in a file ./src/ack/doodle.clj
  • create ./project.clj with these contents:

    (defproject ack "1" :main ack.doodle)

  • run it:

    lein run

2

2 Answers

0
votes

Didn't I answer this for you last night in #clojure? If there's something unsatisfying about the answer, you'll have to clarify your question.

0
votes

It looks like leiningen runs (-main) by calling it from user namespace like that: (ack.doodle/-main). Thus *ns* is bound to the user namespace.

Try running lein repl in your project root. Then run (-main) and see what happens. :)