cla*_*taq 12 validation macros clojure
我在Clojure中有一组数字函数,我想验证参数.函数期望有许多类型的参数,例如正整数,百分比,数字序列,非零数字序列等.我可以通过以下方式验证任何单个函数的参数:
Larry Hunter的一些Lisp代码是#3的一个很好的例子.(寻找test-variables宏.)
我的直觉是宏更合适,因为对评估的控制和编译时计算的潜力,而不是在运行时完成所有操作.但是,我没有遇到我正在编写的代码似乎需要它的用例.我想知道编写这样一个宏是否值得付出努力.
有什么建议?
Bri*_*per 13
Clojure已经(没有文档记录,可能会有更改)支持fns的前后条件.
user> (defn divide [x y]
{:pre [(not= y 0)]}
(/ x y))
user> (divide 1 0)
Assert failed: (not= y 0)
[Thrown class java.lang.Exception]
Run Code Online (Sandbox Code Playgroud)
虽然有点难看.
我可能会编写一个宏,这样我就能以简洁的方式报告哪些测试失败了(引用并按字面打印测试).您链接到的CL代码看起来非常讨厌这个巨大的案例陈述.在我看来,Multimethods在这里会更好.你可以很容易地把这样的东西扔到一起.
(defmacro assert* [val test]
`(let [result# ~test] ;; SO`s syntax-highlighting is terrible
(when (not result#)
(throw (Exception.
(str "Test failed: " (quote ~test)
" for " (quote ~val) " = " ~val))))))
(defmulti validate* (fn [val test] test))
(defmethod validate* :non-zero [x _]
(assert* x (not= x 0)))
(defmethod validate* :even [x _]
(assert* x (even? x)))
(defn validate [& tests]
(doseq [test tests] (apply validate* test)))
(defn divide [x y]
(validate [y :non-zero] [x :even])
(/ x y))
Run Code Online (Sandbox Code Playgroud)
然后:
user> (divide 1 0)
; Evaluation aborted.
; Test failed: (not= x 0) for x = 0
; [Thrown class java.lang.Exception]
user> (divide 5 1)
; Evaluation aborted.
; Test failed: (even? x) for x = 5
; [Thrown class java.lang.Exception]
user> (divide 6 2)
3
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1585 次 |
| 最近记录: |