我一直收到如下错误:
#object[Error Error: No protocol method XXX.YYY defined for type undefined: ]
其中XXX.YYY
部分是可变的。这段代码在* .cljc文件中,可以在JVM Clojure中正常运行,但在ClojureScript中失败。可能是什么原因?
答案 0 :(得分:1)
此晦涩的错误消息可能是由于对JVM类的无意引用导致的,这些JVM类没有使用#?(:clj ...)
和#?(:cljs ...)
阅读器条件进行适当的保护。对于上面的示例,有问题的代码是这样的:
(ns tupelo.schema
"Prismatic Schema type definitions"
(:require [schema.core :as s])
#?(:clj (:import [java.util HashSet] ))
#?(:clj (:gen-class)))
(def Set
"Either a Clojure hash-set or a java.util.HashSet"
(s/either #{s/Any}
java.util.HashSet))
正确的版本如下:
(def Set
"Either a Clojure hash-set or a java.util.HashSet"
(s/either #{s/Any}
#?(:clj java.util.HashSet))) ; <= must guard the java class reference
这些错误特别隐蔽,因为错误消息如此含糊,并且没有引用有问题的文件和行。实际上,在这种情况下,它是由4个文件中的一系列引用引起的:
tst.tupelo.core -> tupelo.core -> tupelo.impl -> tupelo.schema
作为参考,以下是如何成功编写两用CLJ和CLJS代码的示例:
(is (instance?
#?(:clj clojure.lang.PersistentVector)
#?(:cljs cljs.core/PersistentVector)
[1 2 3]))
因此,您可以看到CLJ和CLJS中通常都有等效项,但是名称足够不同,因此您必须正确使用阅读器条件#?(:clj ...)
和#?(:cljs ...)
。否则,您的代码将失败,并显示模糊的错误消息。