1

使用 prismatic/schema 时,defrecord 上的枚举验证不起作用,如下所示:

(s/defrecord Action [type :- (s/enum :a :b)])
#'user/strict-map->Action
user> (Action. "3")            ; this should fail
#user.Action{:type "3"}
user> (Action. 1)              ; this should fail
#user.Action{:type 1}
user> (Action. "abc")          ; this should fail
#user.Action{:type "abc"}

但是,当我将 enum 更改为 long 时,它按预期工作:

(s/defrecord ThisWorks [type :- long])
#'user/strict-map->ThisWorks
user> (ThisWorks. 3)
#user.ThisWorks{:type 3}
user> (ThisWorks. "abc")
ClassCastException java.lang.String cannot be cast to java.lang.Number  user/eval11888 (form-init4803894880546699153.clj:1)

有人知道吗?太感谢了。

4

1 回答 1

3

因为您可以在运行时打开和关闭验证,所以在将记录传递给函数之前不会实际检查它们:

(s/defrecord Action [type :- (s/enum :a :b)])
(s/defn process-action [x :- Action])
(process-action (Action. "3")) ;; => Exception

关于long神奇的工作。由于原语,这只是特殊的 clojure 行为:

字段可以有类型提示,并且可以是原始的

  • 请注意,目前非原始类型的类型提示不会用于约束字段类型或构造函数 arg,但将用于优化其在类方法中的使用

  • 计划约束字段类型和构造函数 arg

(s/defrecord PrimitveRec [foo :- long])
(s/defrecord NonPrimitveRec [foo :- String])


(.? NonPrimitveRec :field #"foo" :type)
;=> (java.lang.Object)
(.? PrimitveRec :field #"foo" :type)
;=> (long)

.?来自Vinyasa的地方

于 2015-11-25T12:51:49.477 回答