天天看点

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,如需转载请自行联系原作者