Это неясное сообщение об ошибке может быть вызвано непреднамеренными ссылками на классы 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 ...)
. В противном случае ваш код потерпит неудачу с неопределенным сообщением об ошибке.