2024年Clojure状态调查!上分享您的想法吧!

欢迎!请查看关于页面以获取更多此功能的信息。

0
错误
当 *compile-path* 没有设置为字符串,而是设置为 java.io.File(boot-clj此时就是这样做的)。当尝试从 boot repl 使用它时,编译器中会出现类型转换异常。似乎普遍的观点是不要从 repl 编译,人们说不要使用 gen-class。我发现在需要使用 gen-class 并快速迭代时,这很不幸。

我没有为所有旧版本测试这个问题,但 git blaming 表明,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*
        corrected-path (cond
                         (instance? java.io.File compile-path-class) (.getAbsolutePath *compile-path*)
                         (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 中有效(由于类路径问题,不是在 Leiningen 和 clj cli 中):https://gist.github.com/jeroenvandijk/8187413d24433545eeb9579538a903f7#file-repl_compile-clj-L39-L52

0

评论由:alexmiller 提出

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

看来 ClassCastException 对于拥有错误类型的类来说是非常准确的。

0
评论由:jeroen 提出

我已经尽量简化了这个例子。你是对的,ClassCastException 的确非常准确,但你在明白它是关于 *compile-path* 之后才会意识到这一点。这个错误报告主要关于管理 Clojure 用户(对 compile-path 的预期)。



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

 ;; clj 的 *compile-path* 已经被正确设置为字符串(尽管不在类路径中)
 *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).
 原因:java.io.File 无法转换为 java.lang.String
 
 
0
参考: https://clojure.atlassian.net/browse/CLJ-2412 (由 jeroen reported)
...