【问题标题】:Clojure spec.alpha - How to (reference another argument) / (describe that argument collection should include values from another argument collection)Clojure spec.alpha - 如何(引用另一个参数)/(描述参数集合应该包含来自另一个参数集合的值)
【发布时间】:2022-01-05 15:41:28
【问题描述】:

我需要什么: 具有两个参数的函数规范:

  • 关键字和字符串的哈希映射。
  • 可能有字符串或关键字的向量如果它是关键字它必须存在于 hash-map 中(第一个参数)

(您的答案不必涵盖所有这些,主要是我需要一种方法来判断它是否是关键字,它必须存在于 hash-map 中)

这是我所拥有的:

(这是一个示例,表明可以访问 :args 中的两个参数,我知道它不会测试任何东西并且总是失败,因为返回 nil)

(ns my-example.core
  (:require
   [clojure.spec.alpha :as spec]))

(defn my-example [m v] nil)

(spec/fdef my-example
  :args (fn [[m v]] nil))

这种 fn 类型的作品(可以创建一个可以按我想要的方式工作的函数),但它不是很有描述性,并且当它失败时(假设有 (stest/instrument `my-example)) 它只是向我展示了函数体(像这样:(fn [[m v]] nil))。

这是解决我的问题的唯一方法还是有更好的方法?

我还尝试定义一个规范并在 :args 中使用它:

(spec/def :my-example/my-check (fn [[m v]] nil))

(spec/fdef my-example
  :args :my-example/my-check)

但结果是一样的。

【问题讨论】:

    标签: clojure clojure.spec


    【解决方案1】:

    :args 的规范中,您可以指定任何您想要的谓词。请参阅spec guide for fdef 提供的示例。鉴于该示例,这是一个主要适用于您的案例的代码片段。我说“大部分”是因为第一个 map 参数的规范可以更严格地注意它是关键字到字符串的映射。 comment 表单中的表单显示了一些使用示例。

    (ns example
      (:require [clojure.spec.alpha :as s]
                [clojure.spec.test.alpha :as stest]))
    
    (defn my-example [m v] nil)
    
    (s/fdef my-example
      :args (s/and (s/cat :m map? :v vector?)
                   #(every? (fn [x] (or (string? x)
                                        (and (keyword? x)
                                             (contains? (:m %) x))))
                            (:v %)))
      :ret nil?)
    
    (comment
      (stest/instrument `my-example)
      (my-example {:a "a" :b "b"} ["foo" :a "bar" :b]) ; => nil
      (my-example {:a "a" :b "b"} ["foo" :a "bar" :c]) ; => spec exception
      (my-example {:a "a" :b "b"} ["foo" :a "bar" 2]) ; => spec exception
      )
    

    【讨论】:

    • 谢谢你的工作,我还发现可以做(def my-check? #(every? (fn [x] (or (string? x) (and (keyword? x) (contains? (:m %) x)))) (:v %))),这样当它失败时它会显示函数的名称而不是它的主体,这更容易理解(如果名称是描述性的)
    • 将其定义为规范也可以,将其定义为规范会更好吗?
    • 正确。使用命名函数将使错误消息更加本地化。
    • 我不认为将my-check? 谓词纳入规范是有用的。规范通常针对一种数据结构,而my-check? 是针对两种数据结构的谓词。
    猜你喜欢
    • 1970-01-01
    • 2022-08-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-09
    • 2022-07-26
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    相关资源
    最近更新 更多