Clojure 根据字段指定子贴图的内容
也许我的问题已经得到了回答,但我仍然坚持使用submap规范 想象一下,我有两种可能性Clojure 根据字段指定子贴图的内容,clojure,clojure.spec,Clojure,Clojure.spec,也许我的问题已经得到了回答,但我仍然坚持使用submap规范 想象一下,我有两种可能性 {:type :a :spec {:name "a"}} {:type :b :spec {:id "b"}} 简而言之::spec键取决于类型。对于类型:a,:spec必须包含字段:name,对于类型:b而言,spec必须包含字段:id 我试过这个: (s/def ::type keyword?) (defmulti input-type ::type) (defmethod input-type
{:type :a
:spec {:name "a"}}
{:type :b
:spec {:id "b"}}
简而言之::spec
键取决于类型。对于类型:a
,:spec
必须包含字段:name
,对于类型:b
而言,spec必须包含字段:id
我试过这个:
(s/def ::type keyword?)
(defmulti input-type ::type)
(defmethod input-type :a
[_]
(s/keys :req-un [::name]))
(defmethod input-type :b
[_]
(s/keys :req-un [::id]))
(s/def ::spec (s/multi input-type ::type))
(s/def ::input (s/keys :req-un [::type ::spec]))
这告诉我:没有方法([:spec nil])。
我想我明白了原因:也许类型是不可访问的。
所以我想制作一个更高级别的多规格(基于整个地图)
问题:我不知道如何根据:type
定义:spec
,因为它们的名称相同。你知道怎么做吗
谢谢
为了适应:spec
映射的两种不同含义,我们可以在不同的名称空间中定义它们::id/spec
和:name/spec
。请注意,这些关键字的非命名空间后缀都是spec
,而我们的keys
规范使用的是未命名的关键字。这里这些是“假”名称空间,但您也可以在项目中的其他“真”名称空间中定义它们
(defmulti input-type :type)
(defmethod input-type :a [_]
(s/keys :req-un [::type :name/spec]))
(defmethod input-type :b [_]
(s/keys :req-un [::type :id/spec]))
(s/def ::input (s/multi-spec input-type :type))
(s/valid? ::input {:type :a, :spec {:name "a"}})
=> true
您还可以获取此规范的样本:
(gen/sample (s/gen ::input))
=>
({:type :a, :spec {:name ""}}
{:type :b, :spec {:id "aI"}} ...
为了适应:spec
映射的两种不同含义,我们可以在不同的名称空间中定义它们::id/spec
和:name/spec
。请注意,这些关键字的非命名空间后缀都是spec
,而我们的keys
规范使用的是未命名的关键字。这里这些是“假”名称空间,但您也可以在项目中的其他“真”名称空间中定义它们
(defmulti input-type :type)
(defmethod input-type :a [_]
(s/keys :req-un [::type :name/spec]))
(defmethod input-type :b [_]
(s/keys :req-un [::type :id/spec]))
(s/def ::input (s/multi-spec input-type :type))
(s/valid? ::input {:type :a, :spec {:name "a"}})
=> true
您还可以获取此规范的样本:
(gen/sample (s/gen ::input))
=>
({:type :a, :spec {:name ""}}
{:type :b, :spec {:id "aI"}} ...