如何在Clojure中使宏可用于加载文件?

时间:2010-12-13 08:30:23

标签: namespaces clojure

假设您有以下代码:

(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

找到

现在我在文件“project.clj”上调用read-project,其中包含以下内容:

(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 个答案:

答案 0 :(得分:1)

project.clj确实不知道在哪里寻找foo / defproject。所以,如果你正在进行repl,你可以做到

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

这将从foo命名空间中的project.clj运行代码,其中定义了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始终可用。