由于有过一点点Lisp的基础,所以这个笔记可能并不能完全适应于给别人参考,只是自己学习Clojure的一些笔记。
流控制
Clojure和Lisp类似,都只提供了非常少的流控制语句,从语言设计的初衷来看,函数式语言应该尽量缩短每一个函数的大小,减少复杂的函数内流控制语句。复杂的逻辑应该由函数之间的调用来实现。
if
举例如下:
(defn is-small? [number] (if (< number 100) "yes"))
if语句在Lisp中不是函数,因为正常的函数调用都会先对所有的参数求值,之后再调用函数。而if语句的需求(如果条件为真才执行)又不允许对参数先求值,因此在Lisp中if使用宏实现的,Clojure中应该也是。if也支持else配对,不过是隐式的:
(defn is-small? [number] (if (< number 100) "yes" "no"))
这里面“yes”之后的“no”就是else语句。
do
if语句每一个分支仅仅支持一个语句,而如果你是一个复杂的逻辑怎么办?使用do,do会依次对其参数求值,并返回最后一个表达式的值。比如:
(defn is-small? [number] (if (< number 100) "yes" (do (println "Saw a big number" number) "no" )))
loop/recur
在Clojure中,使用loop和recur来进行循环。Loop和Recur的语法是Lisp中所没有的,因此看起来也很怪异的感觉。Clojure中用recur语句重新绑定loop中绑定的数据,相当于update;而退出loop仅仅是靠其中的if语句。。。
(loop [result [] x 5] (if (zero? x) result (recur (conj result x) (dec x))))
这是一种多么奇怪的表达式啊。但是使用recur可以隐式的创建循环,比如:
(defn countdown [result x] (if (?zero x) result (recur (conj result x) (dec x))))
虽然recur非常有用,但是在Clojure或者Lisp这样的函数式语言中,它是非常少会被用到的,慢慢学习可能就会知道了。