天天看點

Scala:用傳名參數建構并了解循環結構

 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: =&gt; 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,如需轉載請自行聯系原作者