我经常发现自己这样做:
(defn f1 [coll]
(if (not= (count coll) 2)
(throw (IllegalArgumentException. "coll must have length 2.")))
(if (odd? (first coll))
(throw (IllegalArgumentException. "first elem must be even.")))
(if (even? (second coll))
(throw (IllegalArgumentException. "second elem must be odd.")))
(apply * coll))
(defn f2 [coll]
(if (not= (count coll) 2)
(throw (IllegalArgumentException. "coll must have length 2.")))
(if (odd? (first coll))
(throw (IllegalArgumentException. "first elem must be even.")))
(if (even? (second coll))
(throw (IllegalArgumentException. "second elem must be odd.")))
(apply + coll))
(defn f3 [coll]
(if (not= (count coll) 2)
(throw (IllegalArgumentException. "coll must have length 2.")))
(if (odd? (first coll))
(throw (IllegalArgumentException. "first elem must be even.")))
(if (even? (second coll))
(throw (IllegalArgumentException. "second elem must be odd.")))
(apply / coll))
Run Code Online (Sandbox Code Playgroud)
在这个简单的例子中,我可以将共同部分考虑在内:
(defn qc [coll]
(if (not= (count coll) 2)
(throw (IllegalArgumentException. "coll must have length 2.")))
(if (odd? (first coll))
(throw (IllegalArgumentException. "first elem must be even.")))
(if (even? (second coll))
(throw (IllegalArgumentException. "second elem must be odd."))))
(defn f1 [coll]
(qc coll)
(apply + coll))
(defn f2 [coll]
(qc coll)
(apply - coll))
(defn f3 [coll]
(qc coll)
(apply / coll))
Run Code Online (Sandbox Code Playgroud)
但在现实世界的应用程序中,这很快就会变得乏味.如果这些功能的qc步骤都略有不同怎么办?如果我想强加某些类型限制怎么办?
我认为这是动态类型的缺点之一,但也许有一种方法可以使clojure更容易?
函数表单已建立在前后条件:
user> (defn f1 [coll]
{:pre [(= (count coll) 2)
(odd? (first coll))
(even? (second coll))]}
(apply * coll))
#'user/f1
user> (f1 [1])
AssertionError Assert failed: (= (count coll) 2) user/f1 (form-init2783181480380820413.clj:1)
user> (f1 [2 2])
AssertionError Assert failed: (odd? (first coll)) user/f1 (form-init2783181480380820413.clj:1)
user> (f1 [1 2])
2
Run Code Online (Sandbox Code Playgroud)
这些不打印好消息,虽然它打印失败的表达式,因此您可以清楚地写出来以获取消息.