Clojure语法学习-循环
do和塊語句
在Scala中,花括號{}括起來的語句構成一個block,它的值就是最后一個語句的值。
scala> val a = {| println("a")| 1} a a: Int = 1{println("a"); 1}的值為1。
在Clojure中,有時需要使多個form組成一個block, 這個block的值是最后一個form的值。這時候就用do
user=> (def a (do (println "a") 1)) a #'user/a user=> a 1do takes any number of forms, evaluates them all, and returns the last.
do接受任意多的form作為參數,對它們分別求值,然后返回最后一個form的值。
?循環
有哪些要素才能構成一個循環?
在Java中
在Clojure中
也就是說Java需要我們告訴它什么時候退出循環,而Clojure需要我們告訴它何時繼續循環。
Java的for循環是這樣的
for(int i = 0; i < 10; i++)System.out.println(i);可以認為 i< 10, i++以及System.out.println(i)構成了循環體。退出條件為i<10。
while循環與for循環的不同之處在于while無法聲明只在循環內部使用的變量。在上邊的for循環中, i只在循環內部使用。如果我們想讓while有類似的功能(當然,while沒這功能),那么while需要接受一個初始化語法,變成
while(int i = 0)(i < 10){println(i);i++; }?在Clojure中,同樣可以以binding的形式提供初始化語句, 以及提供循環體。這通過loop這種form來實現
(loop [bindings *] exprs*)
這就類似前邊這個加強版的while。同時,在while循環中需要break來打破循環; 在Clojure中,我們需要一種form來繼續循環,這就是recur。可以認為Java的循環是主動的,而Clojure中的是被動的,你必須在代碼中驅動它前進。
(loop [a 0] (if (< a 10) (do (println a) (recur (+ 1 a)))))recur使得程序重新開始執行loop。但是如何程序中是簡單地重新執行loop,它就只是原地踏步,因為所有的綁定都始終是初始值。所以recur不僅轉變了程序的執行流,而且修改了loop開始的綁定。即,recur使得loop開始對a的綁定變成了(+ 1 a)。
假如,我們在loop開始的時候多提供一個綁定
(loop [a 0 b 1] (if (< a 10) (do (println a) (recur (+ 1 a)))))REPL就會告訴我們提供給recur的參數個數不對
CompilerException java.lang.IllegalArgumentException: Mismatched argument count to recur, expected: 2 args, got: 1
實際上,recur不僅可以用于loop,也可以用于函數,它使得函數被重新執行。
舉個書上的例子
(defn countdown [result x] (if (zero? x) result (recur (conj result x) (dec x))))執行(count down [] 5)會輸出返回值[5 4 3 2 1]
這種代碼怎么看著這么眼熟呢?這不就像是尾遞歸嗎?
?
轉載于:https://www.cnblogs.com/devos/p/4207707.html
總結
以上是生活随笔為你收集整理的Clojure语法学习-循环的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 在script所在位置插入内容
- 下一篇: 17.C#类型判断和重载决策(九章9.4