2

我正在尝试从另一个 .clj 文件中加载和/或编译 .clj 文件。我这样做是因为我试图加载的文件只包含一堆地图,我打算最终用一个 xml 文件替换它们。我可以只是:use该文件,它会工作,但我正在尝试通过加载外部数据束的练习。

通过对 repl 的一些随机黑客攻击(通过 emacs 等),我能够以(load "default_libs")某种(compile...)方式(使用命名空间限定符、'和的不同组合")并获得对地图的访问权限,但是在重新启动 repl 后它没有任何工作更多,无论如何我不得不使用完整的命名空间名称来获取数据。

这是 lib_manager.clj:

(ns mycad.lib-manager
  (:use [clojure repl]
        [mycad utils]))

(compile 'mycad.default-libs)
(println mycad.default-libs/default-symbols) 

这是我要加载的文件,default_libs.clj. 这里的数据最终会是一些 xml 文件,但我还是很陌生,所以现在我只是直接写了一堆 clojure 映射。

(ns mycad.default-libs)
(def default-symbols {.... })

所以问题是我怎样才能从一个文件中加载一堆数据.clj而不真正将其加载到命名空间中,(ns...)而是使用loador将其视为数据源compile

谢谢你的帮助

4

2 回答 2

2

如您在问题前面所述compile,将示例中的更改为 a 。load然后该示例将起作用。

compile用于命名空间的 AOT 编译。所以这不是你需要的。

如果只定义了一个地图,您可以使用load-file.

(def default-symbols (load-file "/file/path.clj"))

如果“文件”实际上位于类路径中的某个位置或其他一些非本地流中,则存在load-string.

(def default-symbols (load-string (slurp (io/reader stream))))
于 2012-07-25T09:04:52.453 回答
0

Lisp 是非常动态的语言。Clojure 是 Lisp,允许您执行以下操作:

user=> (eval (read-string "(def a 10)"))
#'user/a
user=> a
10

read-all所以你可以从这里加载你的文件,例如使用一个函数,然后(eval是所有表单:

(use 'clojure.java.io) ; for (reader ..) function
(import 'java.io.PushbackReader)
....
(doseq [f (read-all (PushbackReader. (reader "your/file.clj")))] (eval f))

然后,如果您仅file.clj包含(def初始值,它们将位于您当前的命名空间中,那么您可以将它们用作简单变量。但是,如果您file.clj包含一些更改名称空间的表单((ns..), (in-ns ..)),那么事情可能会很复杂,因为当前的名称空间会发生变化。如果此类声明是强制性的并且不能在文件本身中删除,您可以尝试过滤它们,(eval仅当它是定义时才使用表单。

更新:嗯,我发现(eval+(read-all在某种意义上等同于(load-file

(load-file "your/file.clj")

但是在load-file命名空间不会改变的情况下,即使有命名空间更改命令 - 这些命名空间只是加载到内存中,您可以像往常一样引用其中的符号。看来这就是您所需要的。

于 2012-07-25T13:40:52.137 回答