【问题标题】:clojure spec: map containing either a :with or a :height (XOR)clojure 规范:包含 :with 或 :height (XOR) 的映射
【发布时间】:2017-06-13 11:05:14
【问题描述】:

以下 clojure 规范 ::my 允许映射具有键 :width 或键 :height,但不允许同时具有它们:

(s/def ::width int?)

(s/def ::height int?)

(defn one-of-both? [a b]
  (or (and a (not b))
      (and b (not a))))

(s/def ::my (s/and (s/keys :opt-un [::width ::height])
                   #(one-of-both? (% :width) (% :height))))

即使它完成了工作:

(s/valid? ::my {})
false
(s/valid? ::my {:width 5})
true
(s/valid? ::my {:height 2})
true
(s/valid? ::my {:width 5 :height 2})
false

代码在我看来并不那么简洁。首先将键定义为可选的,然后根据需要定义。有没有人对此有更易读的解决方案?

【问题讨论】:

  • 只是想指出,如果任何一个键持有的值是假的,即falsenil(spec/valid? ::my {:width nil}) => false,上述逻辑就会失败。跨度>

标签: clojure clojure.spec


【解决方案1】:

只是想对原始问题中的规范进行小幅修改

(spec/valid? ::my {:width nil})
=> false

当然,这不会发生在int? 的给定约束放在问题中的值上。但也许后人允许他们的值是 nilable 或 boolean 在这种情况下这个答案很方便。

如果我们将规范定义为:

(defn xor? [coll a-key b-key]
  (let [a (contains? coll a-key)
        b (contains? coll b-key)]
    (or (and a (not b))
        (and b (not a)))))

(spec/def ::my (spec/and (spec/keys :opt-un [::width ::height])
                         #(xor? % :width :height)))

我们得到的结果是

(spec/valid? ::my {:width nil})
=> true
(spec/valid? ::my {:width nil :height 5})
=> false

【讨论】:

    【解决方案2】:

    此功能内置于规范中 - 您可以在 req-un 中指定和/或模式:

    (s/def ::my (s/keys :req-un [(or ::width ::height)]))
    :user/my
    user=> (s/valid? ::my {})
    false
    user=> (s/valid? ::my {:width 5})
    true
    user=> (s/valid? ::my {:height 2})
    true
    user=> (s/valid? ::my {:width 5 :height 2})
    true
    

    【讨论】:

      【解决方案3】:

      clojure.spec 旨在鼓励能够增长的规范。因此它的s/keys 不支持禁止键。它甚至匹配具有既不在:reqopt 中的键的映射。

      但是有一种方法可以说地图必须至少:width :height,即不是异或,只是或。

      (s/def ::my (s/keys :req-un [(or ::width ::height)]))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-11-20
        • 2017-09-13
        • 1970-01-01
        • 1970-01-01
        • 2019-11-29
        • 1970-01-01
        • 1970-01-01
        • 2011-02-10
        相关资源
        最近更新 更多