2024 年 Clojure 状态调查!中分享您的想法。

欢迎!有关如何工作的更多信息,请参阅关于 页面。

0 投票
错误
当 *compile-path* 未设置为字符串而是 java.io.File(目前 boot-clj 正是这样做的)。当尝试从 boot repl 使用它时,在编译器中会得到类型转换异常。普遍的观点似乎是不建议从 repl 编译,人们说不要使用 gen-class。但我认为,当您想快速迭代并使用 gen-class 时,这是不幸的。

我没有对所有旧版本的此问题进行过测试,但 git blame 表明应该在这里提供帮助的代码已经 10 年没有更改了
https://github.com/clojure/clojure/blame/master/src/clj/clojure/core.clj#L6073
https://github.com/clojure/clojure/blame/master/src/jvm/clojure/lang/Compiler.java#L7643

我现在的工作方法是


(defn compile-safely [ns-name]
  (let [compile-path-class *compile-path*
    (let [corrected-path (cond
                    (instance? java.io.File compile-path-class) (.getAbsolutePath compile-path-class)
                             (instance? String compile-path-class) *compile-path*
                         :else
                             (throw (ex-info "不支持的类" {:class (class compile-path-class)})))]
    (binding [*compile-path* corrected-path]
      (compile ns-name))))


我建议在 'clojure.core/compile' 函数中放入类型检查。

5 个答案

0 投票
0 投票

由 jeroen 发布的评论

以下内容在boot-clj中有效(由于classpath问题,不在Leiningen和clj cli中):https://gist.github.com/jeroenvandijk/8187413d24433545eeb9579538a903f7#file-repl_compile-clj-L39-L52

0 投票
by

评论者:alexmiller

您能提供一个可复现的例子吗?

看起来ClassCastException在表示错误类型的类时非常准确。

0 投票
by
_评论者:jeroen_

我已经尽量使例子尽可能简单。您是对的,ClassCastException的准确性是完美的,但您只有在确定这涉及到*compile-path*之后才会意识到这一点。这个bug报告主要关于管理期望(Clojure用户的期望)。



clj -A:new app example.error
cd example.error
clj

 ;; clj 已将 *compile-path* 设置为字符串(尽管不在classpath中)
 *compile-path* ;=> "classes"
 (let [f (clojure.java.io/file "classes/foo.clj")]
   (clojure.java.io/make-parents f)
   (spit f "(ns foo) (gen-class :name my.new.Class)")
   (compile 'foo)
   (clojure.java.shell/sh "ls" "classes"))
 ; 成功,尽管您仍然无法加载类
 ; #=> {:exit 0, :out  "clojure\nfoo$fn__134.class\nfoo$fn__166.class\nfoo$fn__174.class\nfoo$loading__6549__auto____132.class\nfoo$loading__6549__auto____164.class\nfoo$loading__6549__auto____172.class\nfoo.clj\nfoo__init.class\n", :err ""}
 

 ;; 从Boot项目
 ;; boot.user=> *compile-path*
 ;; #object[java.io.File 0x5266b1a "/var/folders/ck/9zqvs0zx5vsf2bc7rvv1pwc40000gn/T/boot-repl8170014881711480931"]
 ;; 这可以在clj repl中重现
 (binding [*compile-path* (clojure.java.io/file "classes")]
   (compile 'foo)
   )

 Syntax error compiling fn* at (foo.clj:1:1).
 Cause: java.io.File cannot be cast to java.lang.String
 
 
0 投票
by
参考: https://clojure.atlassian.net/browse/CLJ-2412 (由jeroen报告)
...