从多规格中选择一个规格的首选方法是什么?例如。
(defmulti entity :entity)
(s/def ::e1
(s/keys :req [:e1/attr1
:e1/attr2
:e1/attrN]))
(defmethod entity :e1 [_] ::e1)
(s/def ::e2
(s/merge
::e1
(s/keys :req [:e2/attr1
:e2/attr2
:e2/attrN])))
(defmethod entity :e2 [_] ::e2)
(s/def ::entity (s/multi-spec entity :entity))
如何为只接受 ::e2
实体作为参数的函数指定规范?... 或者如何生成仅包含 ::e2
实体值?
不能做 (s/cat :e2 ::e2)
或 (s/gen ::e2)
,因为 ::e2
没有所需的 :entity
标签。同样,不能向 ::e1
和 ::e2
添加 :req-un [:e1/entity]
和 :req-un [:e2/entity]
,因为这将在 s/merge
中冲突。
我找到的最简单方法是使用 s/and
,例如
(gen/generate (s/gen (s/and ::entity ::e2)))
但对于接受任何实体的同质集合的函数的生成数据来说,这仍然很困难
(s/and (s/coll-of ::entity :min-count 1)
#(->> % (map :entity) (apply =)))
如果能传递实体标签以选择特定的实体规范或生成器,将会更容易,例如,生成随机实体,并根据其实体标签生成其他元素。
换句话说,我正在寻找一种方法,通过 :e2
标签以某种方式获取 ::e2
实体规范,而无需维护一个全局辅助映射...
或者有没有其他解决方案?