yinwuzhe 2013-03-15
二、异常处理
Clojure代码里面抛出来的异常都是运行时异常。当然从Clojure代码里面调用的java代码还是可能抛出那种需要检查的异常的。try,catch,finally以及throw提供了和java里面类似的功能:
try、catch、throw、finally:
user=> (try (throw (Exception. "error")) (finally (println "final"))) final Exception error user/eval310 (NO_SOURCE_FILE:1)
user=> (try (/ 3 0) (catch Exception e (println e))) #<ArithmeticException java.lang.ArithmeticException: Divide by zero> nil
assert:
它测试一个表达式,如果这个表达式的值为false的话,它会抛出异常。
user=> (assert true) nil user=> (assert false) AssertionError Assert failed: false user/eval317 (NO_SOURCE_FILE:1) user=> (assert nil) AssertionError Assert failed: nil user/eval319 (NO_SOURCE_FILE:1) user=> (assert 0) nil user=> (assert [1 2 3]) nil user=> (assert "foo") nil
三、基于函数的流程控制
repeatedly:
repeatedly字面意思为重复函数。一般的用法如下:
user=> (repeatedly 5 #(rand-int 11)) (6 8 2 6 6)
重复产生5次随机数。rand-int11表示0至11的随机数。
这里顺便提一下repeat函数:repeat函数接受一/两个常量参数,用法如下:
user=> (repeat 5 (int (rand-int 100))) (30 30 30 30 30)
当repeat、repeatedly函数只接受一个参数时(即没有重复次数的参数),需要配合take来中止,否则会产生内存溢出的错误。如下:
user=> (repeatedly #(rand-int 11)) OutOfMemoryError Java heap space java.util.Arrays.copyOf (Arrays.java:2882) user=> (take 5 (repeatedly #(rand-int 11))) (10 7 0 2 8)
iterate:
迭代函数形式如下:
(iteratefv)
相当于:
while(true){v=f(v)}
所以一般要配合(takensequence)来中止:
user=> (take 10 (iterate inc 5)) ; (5 6 7 8 9 10 11 12 13 14) user=> (take 10 (iterate #(+ % 5) 5)) ; (5 10 15 20 25 30 35 40 45 50) user=> (take 10 (iterate #(* % 2) 2)) ; (2 4 8 16 32 64 128 256 512 1024)
四、基于序列的流程控制
dotimes:
dotimes会执行给定的表达式一定次数,一个本地binding会被给定值:从0到一个给定的数值。如下:
user=> (dotimes [num 3] (println "number:" (inc num))) number: 1 number: 2 number: 3 nil
doseq:
doseq和for的语法是一样的,只不过for返回lazyseq而doseq接受任意数量的表达式,以有副作用的方式执行它们,并且返回nil
user=> (doseq [i (range 10)] (println i)) 0 1 2 3 4 5 6 7 8 9 nil user=> (doseq [i [1 2 3] j [10 20]] (println i "-" j)) 1 - 10 1 - 20 2 - 10 2 - 20 3 - 10 3 - 20 nil
for:
for、doseq都支持遍历多个集合(最右边的最快),同时还可以用:when和:while来过滤。
user=> (for [x (range 3 7)] (* x x)) (9 16 25 36) user=> (for [x [0 1 2 3 4 5] :let [y (* x 3)] :when (even? y)] y) (0 6 12)
上面第二条语句可理解为:先定义x为集合,再使用let将y赋值为x*3,最后判断y是否为偶数,偶数才返回