Scala 中允許無參數的函數作為另一函數的參數傳遞進去,也就是傳名參數(call-by-name)。函數在 Scala 中是第一類公民(first-class citizen),其實函數也是一種特殊的對象,既然實質上是對象,當然也就能夠作為另一個函數的參數傳遞進去了。
我們可以用傳名參數以及尾遞歸來實作一個很熟悉的文法結構 while 循環,代碼如下面的 myWhile 函數:
def myWhile(cond: => Boolean)(body: => Unit): Unit = {
if(cond){
body // 方法體内必須包含循環條件的修改
myWhile(cond)(body)
}
}
var num = 10
myWhile(num > 0){
println(num)
num -= 1 // 此句修改循環的條件
注意我們在上面的myWhile 函數中的 body 必須含有驅使循環趨向結束的語句,即函數體中包含修改 cond 條件的語句。否則,在myWhile(cond)(body) 中則可能會出現每次if(cond) 都為 true 的情況,那就成了毫無用處的死循環了。
我們都很熟悉其他程式設計語言中的 while 循環結構,但是具體它們是不是被設計成尾遞歸的形式得以實作的,我也不清楚。不過書上說 Scala 中的尾遞歸調用會被 Scala 編譯器優化成實際跟常見的 while 循環。是以,我覺得其他語言中的 while 循環結構應該不是用上面這種方法實作的。
覺得 Scala 中這種可以建構自己所需的語言結構确實挺有趣,也比較啟發習慣于指令式程式設計的我。呵呵…
同樣,既然可以類似的實作 while 循環結構,我們也可以實作 do-while 循環,代碼如下:
class DoWhile(body: => Unit){
// 相當于do-while中的while
def doWhile(cond: => Boolean){
body
if(<b>!cond</b>) doWhile(cond) // 都傳入cond且真值剛好相反
}
// 相當于do,傳回DoWhile類執行個體
def myDo(body: => Unit): DoWhile = <b>new</b> DoWhile(body)
// 測試
myDo{
print(num + " ")
num -= 1
} <b>doWhile</b>(num == 0) //myDo傳回DoWhile執行個體,再調用其doWhile函數
在上面這個例子中,之是以要設計出一個DoWhile 類,并且定義了myDo函數的傳回類型為DoWhile 類執行個體,是為了讓傳回的DoWhile 類執行個體直接調用其<b>doWhile </b>函數。這樣一來,就非常類似于常見的 do-while 循環結構了。
同樣,myDo 函數中 body 也必須且将會修改 cond 以使循環趨向結束。此外還應該注意if(<b>!cond</b>) doWhile(cond) 一句中判斷是否繼續調用doWhile 函數與傳入doWhile 函數的 cond 是剛好相反的。
本文轉自 xxxx66yyyy 51CTO部落格,原文連結:http://blog.51cto.com/haolloyin/388232,如需轉載請自行聯系原作者