2012-07-25 22 views
2

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

通过围绕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...)命名空间,而是把它当作使用或者loadcompile数据的来源?

感谢所有帮助

回答

2

更改compile在您的示例为load,你在你的问题之前描述它。那么这个例子将起作用。

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

如果只定义了一张地图,则可以使用load-file

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

在情况下,“文件”,实际上是在类路径或其他一些非本地流的地方,有load-string

(def default-symbols (load-string (slurp (io/reader stream)))) 
0

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

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

因此,您可以加载文件,例如具有功能read-allhere,然后(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 initions,他们会在你当前的命名空间,那么你可以用它们作为简单的变量。但是,如果您的file.clj包含一些命名空间更改表单((ns..),(in-ns ..)),则事情可能会变得复杂,因为当前命名空间将会更改。如果这样的声明是强制性的并且不能在文件本身中被删除,那么您可以尝试对它们进行过滤,只有当它是一个定义时。

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

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

但在load-file的情况下,即使有命名空间不会改变命名空间变化命令 - 这些命名空间只是加载到内存中,您可以照常参考它们中的符号。看来,这是你需要的。