用于谓词函数的Clojure Spec

时间:2017-04-18 14:28:17

标签: clojure clojure.spec

我想写一个关于函数作为谓词的含义的规范。关于Clojure世界中的谓词似乎有三种方法,尽管大多数人似乎都认为它们应该以问号结尾。

  1. 一个接受一个参数并返回true或false的函数。
  2. 一个函数,它接受一个参数并返回true,false或nil。
  3. 一个函数,它接受一个参数并返回一个truthey或falsey值。
  4. Jira Ticket on what Predicate is

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

2 个答案:

答案 0 :(得分:3)

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

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

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

答案 1 :(得分: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

对于defenition nr。 2:

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

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

对于nr。 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

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

(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"

然而,我们可以尝试猜测生成的函数的作用。但是如果没有能够看到来源,我们将很难检查我们的猜测是否正确。