Clojure在本地目录中找不到.clj ,. 和CLASSPATH上的./classes

aft*_*oon 14 macos clojure

当我评估(使用'hello)加载hello.clj时,REPL会抱怨以下错误:

java.io.FileNotFoundException: Could not locate hello__init.class or hello.clj on classpath:  (NO_SOURCE_FILE:0)
Run Code Online (Sandbox Code Playgroud)

我正在调用这样的REPL:

java -cp "/Library/Java/Extensions/servlet-api-2.5-20081211.jar:... lots of jarfiles ...:/Library/Java/Extensions/clojure-contrib.jar:/Library/Java/Extensions/clojure-1.0.0.jar:./classes/:." jline.ConsoleRunner clojure.lang.Repl
Run Code Online (Sandbox Code Playgroud)

阅读,看起来这个文件在PWD中找不到,但我补充说.走向没有成功的道路:-(.

在OS X 10.6上运行Java 1.6.

我确定我是个白痴,有人可以用LART打我吗?

编辑:我也尝试了ClojureX发行版,并得到了相同的结果.

Mic*_*zyk 15

如果在你的类路径hello.clj$DIR并且$DIR在你的类路径上,则hello.clj需要从头开始(ns hello).如果这是在$DIR/$SUBDIR$DIR在你的类路径,然后hello.clj就要开始(ns $SUBDIR.hello).通常,您的文件名结构和ns名称结构必须匹配,文件名分隔符用.ns名称替换,文件名中的任何_s对应-于ns名称中的s.实际文件的名称必须是命名空间名称的最终组件(可能是唯一的组件,如果文件包含dir在类路径上).

编辑:

一个扩展的例子.没有超出我上面所写的信息,所以如果这对你来说足够了,请跳过它; 但是我知道在开始时让CP正确对我来说是非常痛苦的,所以我决定一步一步地把它写出来,这样某人,某个地方可能会幸免于那种特殊的"学习经历";-).

假设这是您的命名空间定义:

;;; in file "hello.clj"
(ns hello)

(defn hello []
  (println "Hello!"))
Run Code Online (Sandbox Code Playgroud)

然后,如果你把包含hello.clj在你的类路径中的目录放在一起,你就可以去了(use 'hello),REPL应该做你想做的事情.

另一方面,如果你这样做:

;;; in file "hello.clj"
(ns my-namespace)
;;; ...
Run Code Online (Sandbox Code Playgroud)

或这个:

;;; in file "my-filename.clj"
(ns hello)
;;; ...
Run Code Online (Sandbox Code Playgroud)

- 也就是说,如果您在文件名和命名空间名称之间引入不匹配,Clojure将无法找到您的命名空间.

此外,如果您hello.clj输入/path/to/code,但实际上您在类路径上拥有的内容/path/to,即父目录/path/to/code,您需要这样做:

;;; in file "/path/to/code/hello.clj"
(ns code.hello)
;;; ...
Run Code Online (Sandbox Code Playgroud)

然后你就可以了(use 'code.hello).

最后,如果您调用文件my_namespace.clj,则需要调用ns my-namespace(反之亦然).不应使用_命名空间名称中的-s和文件名中的s.

  • 我很惊讶 Clojure 将 Java 的语法包声明和物理目录路径的双重编码更进一步,现在要求文件名本身也是命名空间的一部分——即使不需要代表生成任何类的特定文件。在 CL 中,包与源文件分离。在 Clojure 中,命名空间是否应该与文件分离?命名空间是否应该能够跨越多个贡献源文件?Clojure 文档在这一点上保持沉默。 (2认同)

Art*_*ldt 3

当我从 repl 工作并想要加载文件时,我发现我必须首先调用类似的东西:

(add-classpath "file:///home/arthur/.../src/")
(add-classpath "file:///home/arthur/.../build/")
Run Code Online (Sandbox Code Playgroud)

在 repl 可以在类路径上找到它们之前。我将它们放入一个未包含在 jar 文件中的文件中,并附上一条从其他文件重新加载所有内容的语句。当我构建一个 jar 文件时,我发现我不需要这样做。

  • 请不要这样做!add-classpath *仅*用于实验。常规设置的正确方法就像OP所做的那样:在JVM启动时设置类路径。使用 add-classpath 添加路径经常会被破坏,并且会再次困扰您。这就是 JVM 的设计方式。 (2认同)