【问题标题】:Clojure Spec: How can I spec a tuple as a function argument?Clojure Spec:如何将元组指定为函数参数?
【发布时间】:2020-06-16 01:05:32
【问题描述】:

我在 Clojure 中有一个函数,它接受一个 2 元素向量作为参数:

(defn influence [[school value]])

我想使用我已注册的现有规范为该函数的参数编写一个规范:

(s/fdef influence :args (s/cat :arg (s/cat :school ::school, :value ::value))

但是,这不起作用,嵌套的s/cat 调用在顶层运行,并将::school 的规范应用于整个参数列表。还有一个函数叫做s/tuple,可能建议你可以这样做

(s/fdef ->influence :args (s/cat :influence (s/tuple ::school ::value)))

但这也行不通。 Spec 似乎以某种方式感到困惑并尝试使 spec 名称 符合规范:

val: :my.ns/school fails spec: :my.ns/school at: [:args :school] predicate...

【问题讨论】:

    标签: clojure clojure.spec


    【解决方案1】:

    您可以使用 2 个 args 的常规函数​​开始:

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [clojure.spec.alpha :as s]
        [clojure.spec.test.alpha :as stest]
        ))
    
    (defn name-age
      [name age]
      (format "name=%s  age=%d" name age))
    
    (s/fdef  name-age
      :args (s/cat
              :name string?
              :age pos-int? ) )
    
    (dotest
      (spyx (name-age "joe" 42))
      (stest/instrument `name-age)
      (throws? (spyx (name-age "jill" :24))))
    

    结果

    (name-age ["joe" 42]) => "name=joe  age=42"
    

    然后将其重写为 1 个 arg 的 fn,它是一个元组:

    (ns tst.demo.core
      (:use tupelo.core tupelo.test)
      (:require
        [clojure.spec.alpha :as s]
        [clojure.spec.test.alpha :as stest] ))
    
    (s/def ::name string?)
    (s/def ::age pos-int?)
    (s/def ::na-tup (s/cat :name-arg ::name :age-arg ::age))
    
    (defn name-age
      [na-tup]
      (s/valid? ::na-tup  na-tup)
      (let [[name age] na-tup]
        (s/valid? ::name name)
        (s/valid? ::age age)
        (format "name=%s  age=%d" name age)))
    
    (s/fdef  name-age
      :args (s/cat
              :name ::name
              :age ::age ) )
    
    (dotest
      (spyx (name-age ["joe" 42]))
      (stest/instrument `name-age)
      (throws? (spyx (name-age ["jill" :24]))) )
    

    如果需要,您还可以在 name-age 函数中获取一些解构数据的帮助:

    (s/conform ::na-tup na-tup) => 
        {:name-arg "joe", :age-arg 42}
    

    实时代码示例

    我研究了 Clojure Spec 文档并将它们制作成 may be seen here 的实时单元。可能会在某个时候将它们分解为单独的回购。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-02
      • 2012-09-08
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      • 2012-05-24
      • 2022-01-20
      相关资源
      最近更新 更多