clojure-基本语法-流程控制(一)

来源:互联网 发布:mysql命令大全查询 编辑:程序博客网 时间:2024/06/05 06:00
一、标准的流程控制 
if: 
将一个判断表达式作为它的第一个参数进行求值。如果求值为true,那么就返回它的第二个参数(相当于“then”子句)的求值结果。如果结果为false(包括nil)就返回第三个参数的求值结果(相当于“else”子句),前提是有提供第三个参数并且不为空。 
Java代码  收藏代码
  1. user=> (defn is-small [number] (if (< number 100"yes" "no"))  
  2. #'user/is-small  
  3. user=> (is-small 50)  
  4. "yes"  
  5. user=> (is-small 110)  
  6. "no"  

if条件中除了false和nil,其他都为true: 
Java代码  收藏代码
  1. user=> (if true "true")  
  2. "true"  
  3. user=> (if 0 "true")  
  4. "true"  
  5. user=> (if "" "true")  
  6. "true"  
  7. user=> (if nil "true")  
  8. nil  
  9. user=> (if false "true")  
  10. nil  


if-not: 
跟 if 的用法相同,但是作用是相反的。当逻辑为false的时候会去计算第二个参数的值,为true的时候才计算第三个参数的值 
Java代码  收藏代码
  1. user=> (if-not (zero? 0"no" "yes")  
  2. "yes"  
  3. user=> (if (not (zero? 0)) "no" "yes")  
  4. "yes"  


if-let: 
if-let宏接受两个参数,第一个参数为绑定变量,第二个参数为表达式。并根据第二个表达式参数返回的值确定执行then、else语句。 
Java代码  收藏代码
  1. user=> (defn if-let-test [arg] (if-let [x arg] "true" "false"))  
  2. #'user/if-let-test  
  3. user=> (if-let-test 1)  
  4. "true"  
  5. user=> (if-let-test nil)  
  6. "false"  
  7. user=> (if-let-test false)  
  8. "false"  


when: 
when没有else子句,如果when后面第一个参数为true,则执行条件后的所有语句,否则返回nil。 
Java代码  收藏代码
  1. user=> (when false (println "is true""return true")  
  2. nil  
  3. user=> (when true (println "is true""return true")  
  4. is true  
  5. "return true"  
  6. user=> (def has-value (when true (println "hello world""returned value"))  
  7. hello world  
  8. #'user/has-value  
  9. user=> has-value  
  10. "returned value"  


when-not: 
when-not与when类似,只是第一个参数返回false,才执行后面所有语句,否则返回nil。 
Java代码  收藏代码
  1. user=> (when-not  false (println "is true""return true")  
  2. is true  
  3. "return true"  
  4. user=> (when-not true (println "is true""return true")  
  5. nil  


when-let: 
when-let与if-let类似,只有绑定变量值不是false、nil时,才执行后面所有语句,否则直接返回nil。 
Java代码  收藏代码
  1. user=> (when-let [a true] (println "true""return true")  
  2. true  
  3. "return true"  
  4. user=> (when-let [a false] (println "true"))  
  5. nil  
  6. user=> (when-let [a nil] (println "true"))  
  7. nil  


cond: 
cond 可以有任意个“判断/表达式”对,作为它的参数。如果满足第一个判断,就执行第一个判断对应的表达式。如果没有满足第一个条件,就会尝试后面的判断表达式,以此类推。如果一个都没有满足,那么返回 nil 除非你用一个 :else 关键字放在最后来抓住剩下的所有可能性。cond类似于java中的switch..case..default语句,如: 
Java代码  收藏代码
  1. user=> (defn f [n] (cond (< n 0"<0" (< n 10"<10" :else ">=10"))  
  2. #'user/f  
  3. user=> (f -2)  
  4. "<0"  
  5. user=> (f 2)  
  6. "<10"  
  7. user=> (f 10)  
  8. ">=10"  


case: 
case可以简单理解为java中switch的case,如下 
Java代码  收藏代码
  1. user=> (let [mystr "hello"];首先绑定mystr的值为hello  
  2.           (case mystr    
  3.             "" 0   
  4.             "hello" (count mystr)));case用于匹配mystr的值  
  5. 5       
  6. user=> (let [mystr "no match"]   
  7.           (case mystr    
  8.                 "" 0   
  9.                 "hello" (count mystr)   
  10.                 "default")) ;最后一个表达式只有匹配不成功时才执行  
  11. "default"  

case可以用列表一次匹配多个值: 
Java代码  收藏代码
  1. user=> (defn f [x] (case x  
  2.        (5 10"*5"  
  3.        (3 6 9"*3"  
  4.        "others"))  
  5. #'user/f  
  6. user=> (f 5)  
  7. "*5"  
  8. user=> (f 10)  
  9. "*5"  
  10. user=> (f 6)  
  11. "*3"  
  12. user=> (f 1)  
  13. "others"  


do: 
do执行多条语句,返回最后一条语句值 
Java代码  收藏代码
  1. user=> (def v (do (println 123) (println 321) -1))  
  2. 123  
  3. 321  
  4. #'user/v  
  5. user=> v  
  6. -1  


loop、recur: 
如果递归的层次太深的话,那么可能会产生内存不足的情况。所以一些编程语言利用 “tail call optimization” (TCO)的技术来解决这个问题。在Clojure里面避免这个问题的一个办法是使用loop 和recur。 
Java代码  收藏代码
  1. ;定义递归语句完成10+9+……1=55  
  2. user=> (loop [sum 0 cnt 10] (if (= cnt 0) sum (recur (+ cnt sum) (dec cnt))))  
  3. 55  

loop/recur 组合把一个看似递归的调用变成一个迭代 — 迭代不需要占用栈空间。 loop special form 跟let special form 类似的地方是它们都会建立一个本地binding,但是同时它也建立一个递归点, 而这个递归点就是recur的参数里面的那个函数。loop给这些binding一个初始值。对recur 的调用使得程序的控制权返回给loop 并且给那些本地binding赋了新的值。给recur传递的参数一定要和loop所创建的binding的个数一样。同样recur只能出现在loop这个special form的最后一行
0 0