没有实现方法: :spec of protocol: #'schema.core/Schema

mun*_*unk 4 clojure

我写了一个宏

(defmacro defendpoint [msg-type url-key schema]
  `(defrecord ~msg-type []
     Create
     (create [entity#]
       (s/validate ~schema entity#)
       (create-entity (~url-key urls) entity#))))
Run Code Online (Sandbox Code Playgroud)

我正在使用它

(defendpoint Location :locations
  {... my schema ...}})

(defendpoint LocationHierarchy :location-hierarchies
  {... my schema ...}})
Run Code Online (Sandbox Code Playgroud)

我第一次使用宏时,它有效

(create  (map->Location
          {... data ...}))

=> { ... json response ...}
Run Code Online (Sandbox Code Playgroud)

但是第二次,它失败了:

(create  (map->LocationHierarchy
          {... data ...}))

=> 1. Unhandled java.lang.IllegalArgumentException
 No implementation of method: :spec of protocol:
 #'schema.core/Schema found for class: ohds.client$fn__32303
Run Code Online (Sandbox Code Playgroud)

我不确定为什么会这样。我希望第二个调用的工作方式与第一个相同,但似乎验证步骤中存在错误。事实上,如果我(s/validate...)从宏中删除,它会按预期工作。所以我不确定这里到底发生了什么。

我创建了一个显示我正在使用的整个文件的要点

mun*_*unk 6

我将介绍我如何解决我的问题,希望该方法可以帮助其他人。

tl;博士

;; Wrong:
(def date-schema (s/both s/Str #(re-matches #"my-regex" %)))
;; Right:
(def date-schema (s/both s/Str (s/pred #(re-matches #"my-regex" %))))
Run Code Online (Sandbox Code Playgroud)

方法

我从错误开始: No implementation of method: :spec of protocol: #'schema.core/Schema found for class: ohds.client$fn__32303

一开始我不确定这意味着什么。:spec of protocol:把我扔了。但我确实看到它提到了schema.core/Schema,所以我阅读了源代码。我发现 Schema 是一个带有方法的协议spec,就像错误所说:/

下一个令人困惑的部分是for class: ohds.client$fn__32303. 我想知道为什么我的命名空间需要实现协议。那没有任何意义。然后我注意到了$fn_32303。这告诉我在错误所在的地方有一个 lambda!

在这一点上,我的假设是我的模式有问题。所以我从我的模式中删除了所有特殊的验证,并s/Str在任何地方使用它来查看它是否有效。确实如此,所以我来对地方了!我一次添加一个特殊验证,直到测试再次失败。问题出在我的日期模式中。

我查看了我在它上面定义的模式,看看有什么不同。在那里我注意到我未能将我的 lambda 包装在s/pred.

道德

Clojure 设计得很好,因此错误消息会准确地告诉您出了什么问题。你只需要理解它。