我正在尝试从另一个.clj文件中加载和/或编译.clj文件。
我这样做是因为我正在尝试加载的文件只包含一堆地图,我打算最终用xml文件替换它们。我只能:use
该文件并且它可以正常工作,但我正在尝试加载一堆外部数据。
通过对repl的一些随机黑客攻击(通过emacs等),我能够以某种方式(load "default_libs")
以及(compile...)
(使用命名空间限定符的不同组合,'
和{ {1}})并且可以访问地图,但是在重新启动repl之后它再也无法工作了,无论如何我必须使用完整的命名空间名称来获取数据。
这是lib_manager.clj:
"
这是我正在尝试加载的文件(ns mycad.lib-manager
(:use [clojure repl]
[mycad utils]))
(compile 'mycad.default-libs)
(println mycad.default-libs/default-symbols)
。这里的数据最终会是一些xml文件,但我现在还很新,所以现在我直接写了一堆clojure地图。
default_libs.clj
所以问题是如何从(ns mycad.default-libs)
(def default-symbols {.... })
文件加载一堆数据而不用.clj
将其真正加载到命名空间中,而是使用{{1}将其视为数据源}或(ns...)
?
感谢您的帮助
答案 0 :(得分: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))))
答案 1 :(得分:0)
Lisps是非常动态的语言。作为Lisp的Clojure允许您执行以下操作:
user=> (eval (read-string "(def a 10)"))
#'user/a
user=> a
10
因此您可以加载您的文件,例如使用here中的函数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
的情况下,即使存在命名空间更改命令,命名空间也不会更改 - 这些命名空间只是加载到内存中,您可以照常引用它们中的符号。看来这就是你需要的。