Clojure 学习入门(15)—— 条件判断

一、标准的流程控制
if:
将一个判断表达式作为它的第一个参数进行求值。如果求值为true,那么就返回它的第二个参数(相当于“then”子句)的求值结果。如果结果为false(包括nil)就返回第三个参数的求值结果(相当于“else”子句),前提是有提供第三个参数并且不为空。

  1. user=>(defnis-small[number](if(<number100)"yes""no"))
  2. #'user/is-small
  3. user=>(is-small50)
  4. "yes"
  5. user=>(is-small110)
  6. "no"

if条件中除了false和nil,其他都为true:
  1. user=>(iftrue"true")
  2. "true"
  3. user=>(if0"true")
  4. "true"
  5. user=>(if"""true")
  6. "true"
  7. user=>(ifnil"true")
  8. nil
  9. user=>(iffalse"true")
  10. nil

if-not:
跟 if 的用法相同,但是作用是相反的。当逻辑为false的时候会去计算第二个参数的值,为true的时候才计算第三个参数的值
  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语句。
  1. user=>(defnif-let-test[arg](if-let[xarg]"true""false"))
  2. #'user/if-let-test
  3. user=>(if-let-test1)
  4. "true"
  5. user=>(if-let-testnil)
  6. "false"
  7. user=>(if-let-testfalse)
  8. "false"

when:
when没有else子句,如果when后面第一个参数为true,则执行条件后的所有语句,否则返回nil。
  1. user=>(whenfalse(println"istrue")"returntrue")
  2. nil
  3. user=>(whentrue(println"istrue")"returntrue")
  4. istrue
  5. "returntrue"
  6. user=>(defhas-value(whentrue(println"helloworld")"returnedvalue"))
  7. helloworld
  8. #'user/has-value
  9. user=>has-value
  10. "returnedvalue"

when-not:
when-not与when类似,只是第一个参数返回false,才执行后面所有语句,否则返回nil。
  1. user=>(when-notfalse(println"istrue")"returntrue")
  2. istrue
  3. "returntrue"
  4. user=>(when-nottrue(println"istrue")"returntrue")
  5. nil

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

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

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

case可以用列表一次匹配多个值:
  1. user=>(defnf[x](casex
  2. (510)"*5"
  3. (369)"*3"
  4. "others"))
  5. #'user/f
  6. user=>(f5)
  7. "*5"
  8. user=>(f10)
  9. "*5"
  10. user=>(f6)
  11. "*3"
  12. user=>(f1)
  13. "others"

do:
do执行多条语句,返回最后一条语句值
  1. user=>(defv(do(println123)(println321)-1))
  2. 123
  3. 321
  4. #'user/v
  5. user=>v
  6. -1

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

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


你可能感兴趣的:(clojure)