Clojure spec.alpha - 如何(引用另一个参数)/(描述参数集合应该包括来自另一个参数集合的值)

Clojure spec.alpha - How to (reference another argument) / (describe that argument collection should include values from another argument collection)

我需要的: 函数的规范,有两个参数:

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

这是我的:

(这个例子表明可以访问 :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)

但结果是一样的

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