gpt4 book ai didi

Clojure Spec - 规范/或嵌套在规范/和中的问题

转载 作者:行者123 更新时间:2023-12-02 13:47:20 30 4
gpt4 key购买 nike

我最近尝试了 Clojure Spec,但遇到了意外的错误消息。我发现,如果您有一个规范/或嵌套在一个规范/中,然后规范函数,在规范/或分支之后,将传递一个一致的值而不是顶级值。

您可以在此处的“v”的打印值中看到这一点(人为的示例):

(spec/valid? (spec/and (spec/or :always-true (constantly true))
(fn [v]
(println "v:" v)
(constantly true)))
nil)
v: [:always-true nil]
=> true

我认为这可能是规范/和文档字符串中有意为之的:

Takes predicate/spec-forms, e.g.

(s/and even? #(< % 42))

Returns a spec that returns the conformed value. Successive conformed values propagate through rest of predicates.

但这对我来说似乎违反直觉,因为它会妨碍规范谓词的重用,因为需要编写它们来接受“[<或分支> <实际值>]”。

如果您有多个规范/或分支,情况会变得更糟:

(spec/valid? (spec/and (spec/or :always-true (constantly true))
(spec/or :also-always-true (constantly true))
(fn [v]
(println "v:" v)
(constantly true)))
nil)
v: [:also-always-true [:always-true nil]]
=> true

我在这里错过了一些基本的东西吗?

最佳答案

But this seems counterintuitive to me as it would hamper reuse of spec predicates

在我看来,这些行为的替代方案不太有吸引力:

  • 默认情况下丢弃s/or的一致标签。如果我们愿意,我们总是可以丢弃它,但我们不希望 clojure.spec 为我们做出这个决定。规范假设我们想知道哪个s/or分支匹配。
  • 不要在 s/and 中传递一致的值,这会牺牲规范/谓词的可组合性。

幸运的是,如有必要,我们可以丢弃 s/or 标签。这里有两个选项:

  • s/or 包裹在s/noncomforming 中。感谢下面 glts 的评论提醒我这个(未记录的)功能!

    (s/valid?
    (s/and
    (s/nonconforming (s/or :s string? :v vector?))
    empty?)
    "")
    => true
  • s/and s/or 规范,其中 s/conformer 会丢弃标签。

    (s/valid?
    (s/and
    (s/and (s/or :s string? :v vector?)
    ;; discard `s/or` tag here
    (s/conformer second))
    empty?)
    [])
    => true

    如果您经常需要这个,您可以使用宏来减少样板:

    (defmacro dkdc-or [& key-pred-forms]
    `(s/and (s/or ~@key-pred-forms) (s/conformer second)))

Things get even worse if you have multiple spec/or branches

如果您正在编写允许替代方案的数据规范(例如 s/ors/alt),并且您将有效替代项“流动”到后续谓词(s/and)中,IMO 在后续谓词中拥有这些知识更普遍有用。我有兴趣看到此类规范的更现实的用例,因为可能有更好的方法来规范它。

关于Clojure Spec - 规范/或嵌套在规范/和中的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51008019/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com