Clojure: пространство имен и -main

Я пытаюсь понять настройки -main и его пространства имен. Пространство имен по умолчанию в функции -main кажется «пользовательским», но может быть вызвана функция, определенная «над» основной функцией в том же файле. Их отсылают? Я запускал это, чтобы узнать:

(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

Вызов (fo) завершается успешно, но очевидно, что символ 'fo неизвестен в текущем пространстве имен *ns*. Что происходит?

Эта проблема возникла у меня при попытке передать имя некоторой функции вместе с некоторыми аргументами в качестве аргументов командной строки для -main.

Действия по воспроизведению

  • вставьте приведенный выше код в файл ./src/ack/doodle.clj
  • #P4# <блочная цитата> #P5#
  • #P6# <блочная цитата> #P7#

person Lars Bohl    schedule 22.04.2012    source источник


Ответы (2)


Разве я не ответил вам прошлой ночью в #clojure? Если есть что-то неудовлетворительное в ответе, вам придется уточнить свой вопрос.

person amalloy    schedule 22.04.2012
comment
Извините, я не смог прочитать ваш ответ вчера, я думаю, что меня отключили, прежде чем я смог его прочитать. Примерно через час я снова присоединился к каналу и спросил, ответил ли кто-нибудь, но не получил ответа. Я не знал, что можно иметь другую привязку пространства имен во время компиляции и во время выполнения. В любом случае, мне до сих пор не совсем понятно, почему вызов (fo) завершается успешно во время выполнения, хотя очевидно, что 'fo не известно в текущем пространстве имен во время выполнения. Так что, возможно, вопрос должен звучать так: как определить, будет ли вызов функции в *ns* успешным? - person Lars Bohl; 23.04.2012
comment
Кроме того, не знал о журнале каналов. ой :D - person Lars Bohl; 23.04.2012
comment
Значение времени выполнения *ns* не влияет на успешные вызовы функций. Во время компиляции компилятор видит, что вы вызываете foo, ищет его в *ns* (который связан в это время) и выдает ссылку на ack.doodle/foo. Во время выполнения эта ссылка уже была разрешена, поэтому значение *ns* не имеет значения (поэтому оно больше не привязано). Однако я не понимаю вашего уточненного вопроса: как определить, будет ли вызов функции в *ns* успешным, для меня не имеет смысла. - person amalloy; 23.04.2012
comment
Спасибо за объяснение, я думаю, что начинаю понимать это немного лучше (и да, глядя на это сейчас, мой уточненный вопрос кажется немного бессмысленным). - person Lars Bohl; 23.04.2012

Похоже, что leiningen запускается (-main), вызывая его из пользовательского пространства имен следующим образом: (ack.doodle/-main). Таким образом, *ns* привязан к пользовательскому пространству имен.

Попробуйте запустить lein repl в корне вашего проекта. Затем запустите (-main) и посмотрите, что произойдет. :)

person 3cityDan    schedule 22.04.2012