在 Clojure 中如何使用带有 :post 条件的现有谓词向量?
How do you use an existing vector of predicates with :post conditions in Clojure?
鉴于 :post
采用稍后评估的形式(例如 {:post [(= 10 %)]}
)。如何动态地将 'pre-made' 函数向量传递给 :post
?
例如:
(def my-post-validator
[prediate1 predicate2 predicate3])
(defn foo [x]
{:post my-post-validator}
x)
这会引发语法错误
Don't know how to create ISeq from: clojure.lang.Symbol
以我的模糊理解,是因为defn是一个宏,而允许:post
中的%
语法的是它在内部被引用..?
我想也许我然后使用宏来传递 'literal' 我想要评估的内容
(defmacro my-post-cond [spec]
'[(assert spec %) (predicate2 %) (predicate n)])
示例:
(defn foo [x]
{:post (my-post-cond :what/ever)}
x)
然而,这种尝试给出了错误:
Can't take value of a macro
有没有办法将事物的向量传递给 :post
而不必内联定义它?
您不能传递预定义谓词的向量,但您可以将多个谓词组合在一个名称下并在 :post
:
中使用该名称
(defn my-post-cond [spec val]
(and
;; Not sure if this is exactly what you want,
;; given that `val` becomes an assert message.
(assert spec val)
(predicate2 val)
;; You used `n` - I assume it was supposed to be `%`.
(predicate val)))
(defn foo [x]
{:post [(my-post-cond :what/ever %)]}
x)
我最初是 pre-
和 post-conditions
的粉丝,但这些年来我已经改变了。
对于简单的事情,我更喜欢使用 Plumatic Schema 不仅可以测试输入和输出,还可以记录它们。
对于更复杂的测试和验证,我只是输入了一个明确的 assert
或类似的。我还在 the Tupelo library 中写了一个辅助函数来减少调试或验证 return 值时的重复等:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn oddly
"Transforms its input. Throws if result is not odd"
[x]
(let [answer (-> x (* 3) (+ 2))]
(with-result answer
(newline)
(println :given x)
(assert (odd? answer))
(println :returning answer))))
(dotest
(is= 5 (oddly 1))
(throws? (oddly 2)))
结果
------------------------------------
Clojure 1.10.3 Java 11.0.11
------------------------------------
Testing tst.demo.core
:given 1
:returning 5
:given 2
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
Passed all tests
因此,使用 println
或 assert
,returned 值很容易看到。如果失败 assert
,将正常抛出异常。
鉴于 :post
采用稍后评估的形式(例如 {:post [(= 10 %)]}
)。如何动态地将 'pre-made' 函数向量传递给 :post
?
例如:
(def my-post-validator
[prediate1 predicate2 predicate3])
(defn foo [x]
{:post my-post-validator}
x)
这会引发语法错误
Don't know how to create ISeq from: clojure.lang.Symbol
以我的模糊理解,是因为defn是一个宏,而允许:post
中的%
语法的是它在内部被引用..?
我想也许我然后使用宏来传递 'literal' 我想要评估的内容
(defmacro my-post-cond [spec]
'[(assert spec %) (predicate2 %) (predicate n)])
示例:
(defn foo [x]
{:post (my-post-cond :what/ever)}
x)
然而,这种尝试给出了错误:
Can't take value of a macro
有没有办法将事物的向量传递给 :post
而不必内联定义它?
您不能传递预定义谓词的向量,但您可以将多个谓词组合在一个名称下并在 :post
:
(defn my-post-cond [spec val]
(and
;; Not sure if this is exactly what you want,
;; given that `val` becomes an assert message.
(assert spec val)
(predicate2 val)
;; You used `n` - I assume it was supposed to be `%`.
(predicate val)))
(defn foo [x]
{:post [(my-post-cond :what/ever %)]}
x)
我最初是 pre-
和 post-conditions
的粉丝,但这些年来我已经改变了。
对于简单的事情,我更喜欢使用 Plumatic Schema 不仅可以测试输入和输出,还可以记录它们。
对于更复杂的测试和验证,我只是输入了一个明确的 assert
或类似的。我还在 the Tupelo library 中写了一个辅助函数来减少调试或验证 return 值时的重复等:
(ns tst.demo.core
(:use tupelo.core tupelo.test))
(defn oddly
"Transforms its input. Throws if result is not odd"
[x]
(let [answer (-> x (* 3) (+ 2))]
(with-result answer
(newline)
(println :given x)
(assert (odd? answer))
(println :returning answer))))
(dotest
(is= 5 (oddly 1))
(throws? (oddly 2)))
结果
------------------------------------
Clojure 1.10.3 Java 11.0.11
------------------------------------
Testing tst.demo.core
:given 1
:returning 5
:given 2
Ran 2 tests containing 2 assertions.
0 failures, 0 errors.
Passed all tests
因此,使用 println
或 assert
,returned 值很容易看到。如果失败 assert
,将正常抛出异常。