3.1 函数定义
Scala除了方法外还支持函数,方法对对象进行操作,而函数则不是,定义函数与Java和C++定义方法类似,需要给出函数的名称、参数和函数体,例如:
def sum(x:Double, y:Double) = x + y
你必须给出所有参数的类型,而参数返回则不一定要指定类型,除非是递归函数。Scala编译器可以通过“=”符号右侧的表达式类型推断出返回的类型。如果函数需要多个表达式完成,可以用代码块,块中的最后一个表达式就是返回的值,例如:
def fac(x:Int) = {
var r = 1
for (i <- 1 to x)
r = r*i
r
} //> fac: (x: Int)Int
当然,也可以用return进行返回,看个人的变成习惯,不过在scala中一般不用return。
在递归函数当中,则必须指定返回的类型,否则编译就会出错:
def fac(n:Int):Int = if (n <= 0) 1 else n * fac(n -1) //> fac: (n: Int)Int
3.2 函数的参数
3.2.1 在Scala中,调用某些函数时可以不显示地给出所有参数值,并且为这些参数设定默认的值,例如:
// 定义个函数,带有默认值
def printStr(first: String, second: String="{", third:String = "}") = second + first + third
//> printStr: (first: String, second: String, third: String)String
println(printStr("scala")) //> {scala}
println(printStr("scala", "*")) //> *scala}
println(printStr("scala", "***", "***")) //> ***scala***
3.2.2 变长参数
有时候,实现一个可以接受可变长度参数列表的函数会更方便,我们在Java开发中就回经常碰到这种情况,在scala中语法格式如下:
def sum(args: Int*) = {
var result = 0
for (arg <- args) result += arg
result
}
调用:
println(sum(1, 2, 3, 4, 5))
如果函数sum被调用时,传入的是单个参数,那么该参数必须是单个整数,而不是一个整数区间,如果想传入一个整数区间,则可以这么写:
println(sum(1 to 100: _*))
_* 这个符号,会将100转换成参数序列。
3.2.3 过程
Scala对于不返回值得函数有特殊的表示法。如果函数体包含在代码块中,但没有前面的等于符号“=”,那么返回的类型就是Unit,这样的函数被称作过程。过程不返回值,调用它仅仅是为了他的副作用。例如:
def box(sss:String) {
var border = "-"*sss.length + "--\n"
println(border + "|" + sss + "|\n" + border)
}
3.3 懒值
当val被声明为lazy时,它的初始化将被推迟,只有首次使用时,才会对它进行初始化,虽然被定义成为了懒值,但并不是没有额外的开销,每次访问懒值,其实都会有个方法被调用,而这个方法将会以线程安全的方式检查该值是否已经被初始化。例如:
scala> lazy val file = scala.io.Source.fromFile("/Users/apple/Downloads/LAX.doc").mkString
file: String = <lazy>
定义一个val名为file,不管这个路径下有没有LAX.doc这个文件,由于该val是lazy,不会去进行检查,如果使用file的时候,发现没有LAX.doc这个文件,则会报错。