Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Validation Clojure中数值参数的验证_Validation_Clojure_Arguments - Fatal编程技术网

Validation Clojure中数值参数的验证

Validation Clojure中数值参数的验证,validation,clojure,arguments,Validation,Clojure,Arguments,我有一个clojure函数: (defn f [arg1 arg2] ...) 我想测试arg1和arg2是否为数字类型(只有数字类型应该通过,而不是数字格式的字符串)。当然,有很多方法可以做到这一点,但我希望尽可能用惯用的方式。建议 编辑:我知道:pre。任何关于这是否是处理此问题的适当/必要方法的评论都将不胜感激。这个数字?函数听起来像是您需要的。可能是测试(和(数字arg1)(数字arg2)) 不久前,Brian Carper建议使用宏和一系列函数来验证不同类型的数值参数: ;; S

我有一个clojure函数:

(defn f [arg1 arg2]
  ...)
我想测试
arg1
arg2
是否为数字类型(只有数字类型应该通过,而不是数字格式的字符串)。当然,有很多方法可以做到这一点,但我希望尽可能用惯用的方式。建议


编辑:我知道
:pre
。任何关于这是否是处理此问题的适当/必要方法的评论都将不胜感激。

这个
数字?
函数听起来像是您需要的。可能是测试
(和(数字arg1)(数字arg2))

不久前,Brian Carper建议使用宏和一系列函数来验证不同类型的数值参数:

;; Suggested by Brian Carper at:
;;http://stackoverflow.com/questions/1640311/should-i-use-a-function-or-a-macro-to-validate-arguments-in-clojure

(defmacro assert* [val test]
  `(let [result# ~test]
     (when (not result#)
       (throw (IllegalArgumentException.
                (str "Test failed: " (quote ~test)
                  " for " (quote ~val) " = " ~val))))))

(defmulti validate* (fn [val test] test))

(defmethod validate* :prob [x _]
  (assert* x (and (number? x) (pos? x) (<= x 1.0))))

(defmethod validate* :posint [x _]
  (assert* x (and (integer? x) (pos? x))))

(defmethod validate* :non-negint [x _]
  (assert* x (and (integer? x) (not (neg? x)))))

(defmethod validate* :posnum [x _]
  (assert* x (and (number? x) (pos? x))))

(defmethod validate* :percentage [x _]
  (assert* x (and (number? x) (pos? x) (<= x 100))))

(defmethod validate* :numseq [x _]
  (assert* x (and (not (empty? x)) (seq? x) (every? number? x))))

(defmethod validate* :nonzero-numseq [x _]
  (assert* x (and (not (empty? x)) (seq? x) (every? #(and (number? %) (not (zero? %))) x))))

(defmethod validate* :posint-seq [x _]
  (assert* x (and (not (empty? x)) (seq? x) (every? #(and (integer? %) (pos? %)) x))))

(defmethod validate* :prob-seq [x _]
  (assert* x (and (not (empty? x)) (seq? x) (every? #(and (number? %) (pos? %) (<= % 1.0)) x))))

(defmethod validate* :default [x _]
  (throw (IllegalArgumentException.
                (str "Unrecognized validation type"))))

(defn validate [& tests]
  (doseq [test tests] (apply validate* test)))

先决条件可以做到这一点:

(defn test [arg1 arg2]
  {:pre [(number? arg1) (number? arg2)]}
  (+ arg1 arg2))

(test 1 2)
=> 3

(test 1 "2")
=> Assert failed: (number? arg2)
请参阅文档。

我就是为了这个目的而发明的

(defn f [a b]
  (+ a b))

(defprecondition f
  :args-numeric
  (fn [a b & more]
    (and (number? a) (number? b))))

(defhandler f
  {:precondition :args-numeric}
  (fn [e & args] (apply str "Failure for argument list: " (vector args))))

(supervise f "illegal" "args")
我在搜索同一事物时发现:

(defmacro verify-my-arg
 "Like assert, except for the following differences:
 1. does not check for *assert* flag
 2. throws IllegalArgumentException"
 [err-msg arg]
 `(if ~arg true
    (throw (IllegalArgumentException. ~err-msg))))
然后你可以这样使用它:

(defn foo [m]
 {:pre [(verify-my-arg "m must be a map" (map? m))]}
 (println m))
我希望有帮助!
(所有积分归谷歌集团中Shantanu Kumar的原始答案)

谢谢-是的,这似乎是我需要的。那
:pre
呢?你认为在这里不用它可以吗?@misterterero:
:pre
在我问原始问题(Clojure pre-1.0)时不存在,我已经习惯了宏。我认为使用宏可以减少输入;例如,假设必须键入
:非零numseq
的条件<代码>:pre可能更适合一次性、非常特定的条件,比如测试特定值,而不是测试整个数字类。谢谢,贾斯汀。如果我不使用
:pre
而使用其他东西,这会是一种不好的形式吗?我碰巧遇到了一个有点困难的情况(尽管我认为你的答案可能是大多数人想要的)。没有更多的细节,我无法做出判断。为什么使用
:pre
很困难?
(defmacro verify-my-arg
 "Like assert, except for the following differences:
 1. does not check for *assert* flag
 2. throws IllegalArgumentException"
 [err-msg arg]
 `(if ~arg true
    (throw (IllegalArgumentException. ~err-msg))))
(defn foo [m]
 {:pre [(verify-my-arg "m must be a map" (map? m))]}
 (println m))