当我使用lein run
时,我的项目设置就像魅力一样。
导致问题的最小情况如下。我有两个文件,如下所示。 core.clj
文件应该抛出错误然后停止。该错误只是一个扩展Java标准Error
的错误。但是,当我在emacs中打开这个文件并打开苹果酒时,我无法正确编译它。
(ns meta-clojure.core
(:import (org.jsoup Jsoup)
(java.lang String)
(meta_clojure.stm RetryEx)))
(defn -main
[& args]
(println "Throwing exception now..")
(throw (RetryEx. "this is broken"))
(println "End of main")
nil)
(ns meta-clojure.stm.RetryEx
(:gen-class :extends java.lang.Error))
现在,正如我所说,当我运行lein run
命令时,它执行得很好。但是,在emacs中,我得到以下堆栈跟踪:
clojure.lang.Compiler$CompilerException: java.lang.ClassNotFoundException: meta_clojure.stm.RetryEx, compiling:(/home/christophe/bitbucket/meta-clojure/src/meta_clojure/core.clj:1:1)
Compiler.java:7142 clojure.lang.Compiler.load
NO_SOURCE_FILE:1 user/eval931
Compiler.java:6703 clojure.lang.Compiler.eval
Compiler.java:6666 clojure.lang.Compiler.eval
core.clj:2927 clojure.core/eval
main.clj:239 clojure.main/repl[fn]
main.clj:239 clojure.main/repl[fn]
main.clj:257 clojure.main/repl[fn]
main.clj:257 clojure.main/repl
RestFn.java:1523 clojure.lang.RestFn.invoke
interruptible_eval.clj:67 clojure.tools.nrepl.middleware.interruptible-eval/evaluate[fn]
AFn.java:152 clojure.lang.AFn.applyToHelper
AFn.java:144 clojure.lang.AFn.applyTo
core.clj:624 clojure.core/apply
core.clj:1862 clojure.core/with-bindings*
RestFn.java:425 clojure.lang.RestFn.invoke
interruptible_eval.clj:51 clojure.tools.nrepl.middleware.interruptible-eval/evaluate
interruptible_eval.clj:183 clojure.tools.nrepl.middleware.interruptible-eval/interruptible-eval[fn]
interruptible_eval.clj:152 clojure.tools.nrepl.middleware.interruptible-eval/run-next[fn]
AFn.java:22 clojure.lang.AFn.run
ThreadPoolExecutor.java:1145 java.util.concurrent.ThreadPoolExecutor.runWorker
ThreadPoolExecutor.java:615 java.util.concurrent.ThreadPoolExecutor$Worker.run
Thread.java:745 java.lang.Thread.run
Caused by: java.lang.ClassNotFoundException: meta_clojure.stm.RetryEx
URLClassLoader.java:366 java.net.URLClassLoader$1.run
URLClassLoader.java:355 java.net.URLClassLoader$1.run
(Unknown Source) java.security.AccessController.doPrivileged
URLClassLoader.java:354 java.net.URLClassLoader.findClass
DynamicClassLoader.java:61 clojure.lang.DynamicClassLoader.findClass
ClassLoader.java:425 java.lang.ClassLoader.loadClass
ClassLoader.java:358 java.lang.ClassLoader.loadClass
(Unknown Source) java.lang.Class.forName0
Class.java:191 java.lang.Class.forName
core.clj:1 meta-clojure.core/eval935[fn]
core.clj:1 meta-clojure.core/eval935
Compiler.java:6703 clojure.lang.Compiler.eval
Compiler.java:6692 clojure.lang.Compiler.eval
Compiler.java:7130 clojure.lang.Compiler.load
有人可以帮帮我吗?我想我需要告诉Cider / Emacs提前编译或者其他东西。也许leiningen编译到不同的目录而不是emacs?
答案 0 :(得分:1)
您是正确的,您需要编译meta-clojure.stm.RetryEx命名空间以生成类文件,然后才能包含它。如果你正在编写一个供Java库和core使用的类,这有时很有用.clj只是开发的测试工具,尽管它不是简单或典型的方法。使用Clojure项目使用require而不是include来引用clojure命名空间更为常见。
您可以通过查看项目的target/classes
目录来检查实际编译的内容。在编译之前我看到了:
arthur@a:~/meta-clojure$ ls target/classes/
META-INF
然后从repl:
编译它user> (compile 'meta-clojure.stm.RetryEx)
meta-clojure.stm.RetryEx
user>
meta-clojure.core> (-main )
Throwing exception now..
RetryEx this is broken meta-clojure.core/-main (core.clj:6)
meta-clojure.core>
检查同一目录:
arthur@a:~/meta-clojure$ ls -R target/classes/
target/classes/:
meta_clojure META-INF
target/classes/meta_clojure:
stm
target/classes/meta_clojure/stm:
RetryEx.class RetryEx$fn__3333.class RetryEx$fn__3351.class RetryEx__init.class RetryEx$loading__4958__auto__.class
target/classes/META-INF:
maven
target/classes/META-INF/maven:
meta-clojure
target/classes/META-INF/maven/meta-clojure:
meta-clojure
target/classes/META-INF/maven/meta-clojure/meta-clojure:
pom.properties
如果您指定哪个名称空间需要,Leiningen很乐意为您进行AOT编译:
project.clj:
(defproject meta-clojure "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:license {:name "Eclipse Public License"
:url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.6.0"]]
:aot [meta-clojure.stm.RetryEx])
然后运行lein compile
:
arthur@a:~/meta-clojure$ lein compile
Compiling meta-clojure.stm.RetryEx
arthur@a:~/meta-clojure$ ls target/classes/
meta_clojure/ META-INF/
arthur@a:~/meta-clojure$ ls target/classes/meta_clojure/stm/
PS:默认情况下,您也不需要包含java.lang.String
。