请在2024年Clojure状态调查!中分享您的想法。

欢迎!请参阅关于页面了解有关如何工作的更多信息。

+1
Spec
自定义生成器可以构建(通过fmap/bind)在spec生成器上。最高层的生成器重写不会在自定义生成器内部生效


(require '[clojure.spec :as s])
(require '[clojure.test.check.generators :as gen])

;; 存储单个整数值的映射
(s/def ::val integer?)
(s/def ::body (s/keys :req [::val]))

;; 此规范匹配'body'的字符串形式。
;; (read-string仅用于演示目的)
(s/def ::stringy-body
  (s/with-gen
    (s/and string? #(s/valid? ::body (read-string %)))
    #(gen/fmap pr-str (s/gen ::body))))

(s/valid? ::stringy-body "{:user/val 37}") ;; => true

;; 如预期,生成各种字符串映射
(take 3 (gen/sample (s/gen ::stringy-body)))
;; => ("#:user{:val -1}" "#:user{:val 0}" "#:user{:val -1}")

;; *** 但是重写没有传递过去 ***
(take 3 (gen/sample (s/gen ::stringy-body {::val #(s/gen #{42})})))
;; ("#:user{:val -1}" "#:user{:val 0}" "#:user{:val 0}")


应该考虑在s/gen、s/with-gen等中记录这一点

5 答案

0

评论者为:alexmiller

当你使用with-gen时,你基本上是在覆盖内置的 gen 机制(它支持覆盖)并提供一个您自己的(对于 spec 不可透明)生成器。您不应该期望在自定义生成器内部生效的覆盖。

0

评论者为:mullr

这很有道理,但按照我的预期(并且我在寻找这样的方法),应该可以在传递给s/with-gen函数的那一刻获取覆盖映射,但我找不到任何这样的方法。

0

评论者为:mullr

... 我第一次没有完全理解你的评论。我可以从实现中看到,自定义生成器(内部名为gfn)从不会接收内置规范所具备的任何上下文信息。既然这听起来像是故意的,那么在s/gen或s/with-gen的文档字符串中注明这个限制将会很有用。

0

评论者为:alexmiller

这不是一个疯狂的想法,但在当前实现中,似乎没有其他方法可以做到这一点,除非进行相当重大的更改。

0
参考:https://clojure.atlassian.net/browse/CLJ-2095(由 alex+import 报告)
...