Clojure棱镜/架构defrecord没有枚举运行时验证



当使用棱镜/模式时,在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)

有人知道吗?非常感谢。

因为您可以在运行时打开和关闭验证,所以只有将记录传递到函数中时,才会真正检查它们:

(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。

相关内容

最新更新