1

我想为函数作为谓词的含义编写一个规范。在 Clojure 世界中,似乎有三种方法可以了解谓词是什么,尽管大多数人似乎都同意它们应该以问号结尾。

  1. 接受一个参数并返回真或假的函数。
  2. 接受一个参数并返回 true、false 或 nil 的函数。
  3. 一个函数,它接受一个参数并返回一个真值或假值。

关于 Predicate 是什么的 Jira Ticket

编辑:谓词也可以采用多个参数,例如contains?.

4

2 回答 2

4

我认为谓词的最准确规范是:

(s/fspec :args (s/cat :v any?) :ret any?)

虽然谓词通常返回真/假,但并不要求它们这样做 - 唯一需要的契约是它需要一个值并返回一个将被视为逻辑真值的值。

于 2017-04-20T16:29:46.957 回答
2

如果我理解clojure.spec/fdef正确,它允许我们制定问题中描述的规范。

(spec/fdef ::predicate-1
           :args (spec/cat :arg any?)
           :ret  boolean?)

我们可以通过传递一些我们知道应该通过或未通过测试的示例来对其进行测试:

(spec/valid? ::predicate-1 boolean?)       => true
(spec/valid? ::predicate-1 (fn [a] 5))     => false
(spec/valid? ::predicate-1 (fn [a] true))  => true
(spec/valid? ::predicate-1 (fn [a b] true))=> false
(spec/valid? ::predicate-1 #(= 10 %))      => true
(spec/valid? ::predicate-1 (fn [a] nil))   => false

对于国防号。2:

(spec/fdef ::predicate-2
           :args (spec/cat :arg any?)
           :ret  (spec/nilable boolean?))

(spec/valid? ::predicate-2 (fn [a] nil))   => true

而对于天然橡胶。3 任何接受一个参数的函数都是有效的,因为 clojure 中的所有内容要么是真要么是假。

(spec/fdef ::predicate-3
           :args (spec/cat :arg any?)
           :ret  any?)

(spec/valid? ::predicate-3 identity)       => true
(spec/valid? ::predicate-3 str)            => true

然后我们似乎能够做的一件有趣的事情是让规范为我们生成这样的函数:

(let [p (gen/generate (spec/gen ::pedicate-1))]
  (clojure.string/join
   " " [(p 0) (p 1) (p -1) (p nil) (p 'a) (p :a) (p (fn [a] a))]))
=> "false true true false true false false"

由此我们或许可以尝试猜测生成的函数做了什么。但是如果不能看到源,我们将很难检查我们的猜测是否正确。

于 2017-04-18T14:28:17.183 回答