从多规格中选择一个规格的最佳方法是什么?例如。
(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
标签。同样,也不能将 :req-un [:e1/entity]
和 :req-un [:e2/entity]
添加到 ::e1
和 ::e2
,因为这会在 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
实体规格,而不需要维护全局辅助映射...
或者有没有其他解决方案?