Scala函数
Scala函数简介:
在程序变得庞大时,需要将其分割成更小、更易管理的片段。为分割控制流,Scala为有经验的程序员提供了熟悉的方式:把代码分割成函数。Scala提供了许多Java中没有定义函数的方式。除了作为对象成员函数方法之外,还有内嵌在函数中的函数,函数字面量和函数值。定义函数最通用的方法是作为某个对象的成员。
函数示例:
def main(args: Array[String]): Unit = {
println("Sum : " + addInt(5, 7));
}
def addInt(a: Int, b: Int): Int = {
var sum: Int = 0
sum = a + b
return sum
}
Scala嵌套函数:
我么可以在 Scala 函数内定义函数,定义在函数内的函数称之为局部函数。
以下实例我们实现阶乘运算,并使用内嵌函数:
def factorial(i: Int): Int = {
def fact(i: Int, accumulator: Int): Int = {
if (i <= 1)
accumulator
else
fact(i - 1, i * accumulator)
}
fact(i, 1)
}
Scala可变参数函数:
Scala 允许你指明函数的最后一个参数可以是重复的,即我们不需要指定函数参数的个数,可以向函数传入可变长度参数列表。
Scala 通过在参数的类型之后放一个星号来设置可变参数(可重复的参数)。例如:
def sum(args: Int*): Unit ={
var result = 0
for(arg <- args) result += arg
result
}
你可以使用任意多的参数来调用该函数。
例如:
val s = sum(1, 4, 9, 16, 25)
函数得到的是一个类型为Seq的参数,但是如果你已经有一个值得序列,则不能直接将它传入上面的函数,例如如下的写法是不对的:
val s = sum(1 to 5) //错误的
如果sum函数被调用时传入的是单个参数,那么该单个参数必须是单个整数,而不是一个整数区间。解决方法是告诉编译器你希望这个参数被当做参数序列处理。追加:_*,例如下:
val s = sum(1 to 5: _*) //将 1 to 5 当做参数序列处理
默认参数和带名参数:
我们在调用某些函数时并不显示地给出所有参数值,对于这些函数我们可以使用默认参数。例如:
def decorate(str: String, left: String = "[", right: String = "]") = left + str + right
println(decorate("Hello"))
打印结果为[Hello]
这个函数有两个参数,left和right,带有默认值"["和"]" ,如果你不喜欢默认值,可以给出自己喜欢的值:例如 decorate("Hello","<",">") 。
如果你给的参数值不够,默认参数会从后往前逐个应用进来。举例来说decorate("Hello",">"),第二个参数">"会使用right参数的默认值,得到">Hello"。
你也可以在提供参数值的时候指定参数名。例如:
decorate(left = "<", str = "Hello", right = ">")
结果是<Hello> 注意:带名参数并不需要跟参数列表的顺序完全一致。
本地函数:
把函数定义在别的函数之内,就好像本地变量一样。
object LongLines {
def processFile(filename: String, width: Int): Unit = {
def processLine(line: String): Unit = {
if (line.length > width)
print(filename + " : " + line)
}
val source = Source.fromFile(filename)
for (line <- source.getLines)
processLine(line)
}
}
头等函数:
Scala的函数时头等函数。你不仅可以定义和调用函数,还可以把它们写成匿名的字面量,并把它们作为值传递。
示例:
var increase = (x: Int) => x + 1
Increase(10)
=>指明这个函数把左边的东西(任何整数x)转变成右边的东西(x+1)。所以这个函数可以把任意整数x映射为x+1。
如果你想让函数字面量包含多条语句,可以用花括号包住函数体,一行放一条语句,这样就组成了代码块。与方法一样,当函数值被调用时,所有的语句将被执行,而函数的返回值就是最后一行表达式产生的值。
increase = (x: Int) => {
println("We")
println("are")
println("here!")
x + 1
}
占位符语法:
如果想让函数字面量更加简洁,可以把下划线当做一个或更多参数的占位符,只要每个参数在函数字面量内仅出现一次,比如_ >0 对于检查值是否大于零的函数来说就是非常短的标注:
someNumber.filter(_ > 0)
有时你把下划线当做参数的占位符,编译器可能无法推断缺失的参数类型。例如:假设你只是写_ + _ :
val f = _ + _
这种情况下,你可以使用冒号指定类型:
val f = (_: Int) + (_: Int)
部分应用函数:
尽管前面的例子里下划线替代的只是单个参数,你还可以使用单个下划线替换整个参数列表。例如写成println(_),或者更好的方法是你可以写成println _:
1.to(10).foreach(println _)