代码之家  ›  专栏  ›  技术社区  ›  Alan Thompson

什么原因导致clojurescript中“error:no protocol method xxx.yyy defined for type undefined”而不是clojure?

  •  2
  • Alan Thompson  · 技术社区  · 6 年前

    我犯了如下错误:

    #object[Error Error: No protocol method XXX.YYY defined for type undefined: ]
    

    何处 XXX.YYY 部分是可变的。此代码位于*.cljc文件中,在jvm clojure中运行良好,但在clojurescript中失败。可能是什么原因?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alan Thompson    6 年前

    这个模糊的错误消息可能是由于无意中引用了未被正确保护的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&clj中通常都有等价物,但是名称的差异很大,您必须正确使用reader条件 是吗?(CLJ……) 是吗?(CLJS……) . 否则,代码将失败,并显示一条模糊的错误消息。