Scala函数式编程-读书笔记
- 用递归的方式编写裴波那契数
使用尾递归调用的方式编写裴波那契函数。
def fib(x:Int):Int = {
def go(x:Int, acc:Int):Int = {
if (x == 1) acc
else go(x-1, x + acc)
}
go(x, 1)
}
println(fib(10))
此处可以看到,在fib函数中重新定义了一个go递归调用函数。为什么不用如下的方式:
def fib(x:Int):Int = {
if (x == 1) 1
else x + fib(x-1)
}
因为用x+fib(x-1),就不是尾递归,scala无法自动优化为迭代的方式进行运行,这跟我们用C语言写递归调用时一个效果,递归不停压栈,到出口的地方再不停出栈,直到运行处结果。
尾递归:尾递归简单理解,就是在递归程序中,程序的最后一步是针对自身的调用。所以在上述代码中go函数式尾递归。
2.高阶函数
可以这么理解高阶函数,把一个函数作为参数传入到另外一个函数中使用。
在下图的示例中,我们分别为abs函数和fib函数分别定义了格式化函数,用于打印输出不同方法的结果示例。这种情况下每个数学函数都要一个format函数。
object ScalaTest {
def abs(x:Int):Int = if(x < 0) -x else x
def formatAbs(x:Int):String = {
val msg = "the abs value of %d is %d"
msg.format(x, abs(x))
}
def fib(x:Int):Int = {
def go(x:Int, acc:Int):Int = {
if (x == 1) acc
else go(x-1, x + acc)
}
go(x, 1)
}
def formatFib(x:Int):String = {
val msg = "the fib value of %d is %d"
msg.format(x, fib(x))
}
def main(args: Array[String]): Unit = {
println(formatAbs(-10))
println(formatFib(10))
}
}
我们定义一个抽象程度更高的format函数,把方法作为参数传入,以适用于所有格式化操作。
def formatResult(name:String, x:Int, f:Int=>Int):String = {
val msg = "the %s of %d is %d"
msg.format(name, x, f(x))
}
def main(args: Array[String]): Unit = {
println(formatResult("abs", -10, abs))
println(formatResult("fib", 10, fib))
}
3.多态函数
此处示例是一个作业题,目的是提供一个通用的判定函数,判断一个数据是有序的,有序的标准由一个比较函数决定。
def isSorted[A](as:Array[A], ordered:(A,A)=>Boolean):Boolean = {
def compare(n:Int):Boolean = {
if (n == as.length-1) true
else if (!ordered(as(n), as(n+1))) false
else compare(n+1)
}
compare(0)
}
val intNumbers = Array(1,2,3,4,5,6,7,9)
var result = isSorted(intNumbers, (x:Int, y:Int)=>if(x<=y) true else false)
println("isSorted: " + result)
val floatNumbers = Array(9.4,7.2,6.51)
result = isSorted(floatNumbers, (x:Double, y:Double)=>if(x<=y) true else false)
println("isSorted: " + result)