《Scala by Example》第四章_表达式和函数

 

4.2 参数

  • 用保留字 def 做定义的,如def x = e ,不会直接对e进行估值,而是等到x被使用的时候,再对e进行估值(evaluate)
  • 而用val 进行定义的值,会直接计算值,然后在变量被使用的时候,用这个值代替这个变量
  • Scala默认是使用“值传递”(call-by-value),不过在使用 “=>”之后,会转换成为“字面量传递”(call-by-name) 

4.3 条件表达式

  • 就是if-else,跟Java差不多,也就是那么用的。

4.4 例子:用牛顿算法求平方根

  目的是写一个函数,类似于下面这样:

def sqrt(x : Double) : Double = ...

  用来计算x的平方根。

  首先,定义一个函数用来从最初的猜想(guess)到最后的结果(result)进行迭代求值,代码如下:

def sqrtIter(guess : Double , x : Double) : Double = 
if (isGoodEnough(guess , x )) guess
else sqrtIter(improve(guess , x) , x )

  这里用到了递归。而在函数式语言中,“递归”会经常用到。(还有一个名词叫“尾递归”,可以用来代替while循环)。

  在这个函数中,还有一个返回类型:Double。它是跟在参数列表部分后的。在一个递归函数中,返回类型是强制需要的;对于一个非递归函数,返回类型是可选的。因为类型检查器会从函数右侧推断出函数类型。但即便是这样,写上返回类型也是一件好事。这样代码更有可读性。

  其次,定义两个被调用的函数:一个用来改进guess的函数(inprove)和一个最终判断的函数(isGoogEnough)。以下是定义:

def improve(guess : Double , x : Double) = (guess + x / guess) / 2
def isGoodEnough(guess : Double , x : Double) = 
abs(square(guess) - x ) < 0.001

最后,求根函数(sqrt)自己也是由sqrtIter来定义的:

def sqrt(x : Double) = sqrtIter(1.0 , x)

注:想要正常运行这些代码的前提是要import scala.Math._ 这样才可以使用abs函数。同样,square方法没有找到。最后直接用guess * guess来表示的。

4.5 嵌套函数

  • 为了避免这个函数的使用者看到其它我们自己写的Helper函数,可以把这些Helper函数写在最外的函数里面。这样就形成了嵌套函数(nested Functions)。
  • Scala使用通常用的块结构范围法则(scoping rules)。在外面定义的名字,可以在块内部也可以被看到。

4.6 尾递归(tail recursion)

  定义:通常来说,如果一个函数最后的动作是调用另外一个(也可能是同一个)函数,对于两个函数而言,只需要一个堆空间,这样的调用就是尾调用。

  尾递归,从一点点的分析来看,它所需的Stack空间并没有增多。而比如像“阶乘”这样的运算,它所需的Stack空间是增加的。所以它不是尾递归。

 



 

posted @ 2012-04-08 21:10  peterZ.D  阅读(929)  评论(0)    收藏  举报