Как сделать макросы доступными для загрузки файла в Clojure? - PullRequest
4 голосов
/ 13 декабря 2010

Предположим, у вас есть следующий код:

(ns foo)

(defmacro defproject [project-name version & args]
 ...
)

(defn read-project ([file]
    (load-file file)))

Обновление : полный код можно найти по адресу https://github.com/derkork/intellij-leiningen-plugin/blob/master/src/de/janthomae/leiningenplugin/leiningen/LeiningenProjectFile.clj

Теперь я вызываю read-project для файла "project.clj", который имеет следующее содержимое:

(defproject de.janthomae/leiningenplugin "1.0.0-SNAPSHOT"
  ...
)

И я получаю следующее сообщение об ошибке

java.lang.Exception: Unable to resolve symbol: defproject in this context (project.clj:1)
 at clojure.lang.Compiler.analyze(Compiler.java:4420)
 at clojure.lang.Compiler.analyze(Compiler.java:4366)
 at clojure.lang.Compiler$InvokeExpr.parse(Compiler.java:2828)
 at clojure.lang.Compiler.analyzeSeq(Compiler.java:4594)
 at clojure.lang.Compiler.analyze(Compiler.java:4405)
 at clojure.lang.Compiler.analyze(Compiler.java:4366)

Это говорит мне, что он не находит мой макрос defproject. И я совершенно не понимаю, почему это так, поскольку макрос определен всего на несколько строк впереди. Нужно ли как-то экспортировать его, чтобы его можно было увидеть из файлов, загружаемых с помощью load-file?

1 Ответ

1 голос
/ 13 декабря 2010

project.clj действительно не знает, где искать foo / defproject. Так что, если вы на репле, вы можете сделать

user> (in-ns 'foo)
foo> (read-project "project.clj")

Это запустит код из project.clj внутри пространства имен foo, где определен defproject. Или вы можете поместить (in-ns 'foo) в project.clj. Результат будет таким же.

Но вы также можете написать что-то подобное в project.clj:

(foo/defproject ...)

Это вызовет defproject внутри вашего текущего пространства имен при запуске (foo / read-project "project.clj").


обновление

из test_uberjar.clj:

(def project (binding [*ns* (the-ns 'leiningen.core)]
               (read-project "test_projects/sample_no_aot/project.clj")))

из test_deps.clj:

(:use [leiningen.core :only [read-project defproject]] ...)

Таким образом, defproject всегда доступен при загрузке файла.

...