3

不久前,我询问了关于简单多态模式的问题,那里的答案有一段时间效果很好。

现在我要验证的地图有一个附加值,它取决于另一个键的值。

一个人为的对象示例:

{:type      :foo         {:type      :bert        {:type      :foo
 :foo-param :bar          :bert-size :medium       :foo-param :bar
 :method    :baz          :method    :baz          :method    :bang
 :baz-rate  :max}         :baz-rate  :max}         :bangness  :considerable}

这里的鉴别器是:typeand :method,每个鉴别器都有自己的一组有效的兄弟键和值。

以前只:type存在,并且以下工作:

(def ^:private test-base-schema {:type (s/enum :foo :abc :banana)})

(def test-schema
  (s/conditional #(= (:type %) :foo)
                 (merge test-base-schema {:foo-param s/Keyword})
                 ; other conditions here
                 ))

然而,现在有不止一个鉴别器,条件分支的数量将是组合的。

一种选择是允许{s/Any s/Any}在地图中使用s/both,但我不能允许模式“松散”,因为意外的键/值应该被视为无效。

我也不想更改正在验证的地图的结构,只是为了允许使用这个库进行验证。

有没有一种健全的方法来实现对具有多个条件子模式的映射的严格验证?

4

1 回答 1

6

一个刻薄的答案是,这可能是您的数据模型不太理想的味道,您应该考虑将其重构为具有嵌套结构,例如

{:type-info {:type :foo :foo-param :bar}
 :method-info {:method :baz :baz-rate :max}}

一个(也许)更有帮助的答案是,除了编写一个自定义谓词进行验证之外,我认为使用开箱即用的模式集并不容易。

如果这不是可取的,我想您需要引入一种新的模式类型。幸运的是,这在用户代码(或第三方库)中很容易做到。不幸的是,我没有看到一种简单的方法来以清晰和正交的方式表示这两个概念(严格联合和条件映射结构)(没有将它们组合成一个单一的条件联合模式,或者让联合是条件感知的)。我相信有一种方法,但乍一看对我来说并不明显。

于 2014-06-24T15:04:45.683 回答