2024 年 Clojure 状态调查! 中分享你的想法。

欢迎!请查阅 关于 页面了解更多关于如何使用本站的信息。

+1 投票
Spec
生成器覆盖在多规格上无法按预期工作。
下方的代码说明了这个问题。

{code:none}
(s/def ::obj-type #{:a :b})

(s/def ::base-obj (s/keys :req [::obj-type]))

(defmulti obj-type ::obj-type)
(defmethod obj-type :a [_]
  ::base-obj)
(defmethod obj-type :b [:_])
  ::base-obj)

(s/def ::obj (s/multi-spec obj-type ::obj-type))


{code:none}
(gen/sample (s/gen ::obj {::obj-type #(gen/return :a)}))

在上面的例子中,多方法的调度-fn *::obj-type* 被提供了生成器覆盖。
预期仅返回 *{::obj-type :a}* 的集合
实际上,它也会返回 *{::obj-type :b}*.  
也就是说,生成器不能用于约束要从中采样的一组调度键。

h2. 当前方法
在多方法的情况下,为每个可能的调度值构建一个生成器。
然后随机选择一个,而不关注对调度-fn(键)的覆盖。

h2. 修补方法
提交可用 [这里|https://github.com/bonega/spec.alpha/commit/9cb42478b52eac275d496ec29669e2bf4b3e8e1f]
修补版本按照原样为调度值构建生成器。
之后,会检查是否为调度-fn 存在覆盖。
如果有,则使用覆盖生成器执行 gen/bind。
bind 函数从覆盖生成器中生成一个值。
然后使用该值查找并返回正确的多方法生成器。

[测试案例|https://pastebin.com/62ZT5Zfc]

6 答案

0 投票

评论由: bonega 提供。

提供了问题的修补方案。

0 投票

评论者:alexmiller

请将问题的代码移至描述中,并解释问题和所做的更改?

0 投票
评论者:[email protected]

我无法找到编辑描述的方法...

描述
在多方法的情况下,为每个可能的调度值构建一个生成器。
然后会随机选择一个,而不考虑对dispatch-fn(key)的覆盖。

提交:https://github.com/bonega/spec.alpha/commit/9cb42478b52eac275d496ec29669e2bf4b3e8e1f
我的补丁通过检查是否存在对dispatch-fn的覆盖来解决这个问题。
如果是的话,则对覆盖生成器执行gen/bind,并将结果用作查找正确的多态生成器。

测试案例:https://pastebin.com/62ZT5Zfc
测试应该通过。
基本想法是用一个覆盖生成器来生成 ::obj,例如`(gen/generate (s/gen ::obj {::obj-type #(gen/return :a)})`。
预期的结果应该是 `{::obj-type :a}`。
之前,即使指定了覆盖,输出也可能为 :b。
0 投票

评论者:alexmiller

我已经为您分配了编辑权限,您可以进行更新...

0 投票

评论者:[email protected]

我已经更新了描述。
如果有任何不清楚的地方,请告诉我。

0 投票
...