Scala 基础-函数(第三章)

wiki

1. 函数

1. 语法

1
2
3
4
def 函数名([参数名: 参数类型],...) [: 返回值类型] = {
语句
[return] 返回值
}
  • 如果有参数,必须给出参数类型。如果没有形参,括号可以省略。多个参数使用逗号分隔
  • 只要不是递归函数,就不需要显示指定返回值类型
  • 每行语句不强制用分号结束,但是单行包含多条语句,需要使用它分隔
  • 不用显示调用 return,默认以最后一行结果作为返回值。如果显示的调用了 return,则必须指定返回值类型
  • 可以在函数之中在声明函数
  • val 被声明为 lazy 时,它的初始化将被推迟,直到我们首次对它取值
1
2
3
4
def main(args: Array[String]): Unit = {
lazy val res = sum(10, 20) // 并没有马上初始化,计算sum
println(res) //这里 res 才真正有值
}

2. 调用

  • 在声明参数时,可以设默认值
  • 在调用函数时,可以指定参数名赋予参数值
  • 参数类型后面加上* 表示可以接受多个变长参数
1
2
3
4
5
def decorate(str: String, left: String = "[", right: String = "]") = {
left + str + right
}

decorate("Hello") // => "[Hello]"

2. 偏函数

偏函数指被包在花括号内没有 match 的一组 case 语句, 偏函数是 PartialFunction[A, B] 类型的的一个实例对象, 其中 A,B 分别代表输入和返回参数类型。

1
2
3
4
5
6
7
val 对象名 = { 
//这对大括号及其内部的一组case语句, 就组成了一个偏函数.
case1 => 表达式1
case2 => 表达式2
case3 => 表达式3
...
}

其类型是 PartialFunction[A, B],含有一些内部方法 isDefinedAt、OrElse、 andThen、applyOrElse:

  • isDefinedAt : 这个函数的作用是判断传入来的参数是否在这个偏函数所处理的范围内,类似过滤
  • apply : 用来描述对已经接收的值,进行如何处理
  • orElse : 将多个偏函数组合起来使用,效果类似 case 语句
  • andThen : 相当于方法的连续调用,比如 g(f(x))
  • applyOrElse :它接收2个参数,第一个是调用的参数,第二个是个回调函数。如果第一个调用的参数匹配,返回匹配的值,否则调用回调函数

实战 : 偏函数的应用,取整数的绝对值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//正数处理,只处理正数
val positiveAbs:PartialFunction[Int,Int] = {
case x if x >0 => x
}

//负数处理,只处理负数
val negativeAbs:PartialFunction[Int,Int] = {
case x if x <0 => -x
}

//0处理,只处理0
val zeroAbs:PartialFunction[Int,Int] = {
case 0 => 0
}

//定义最终的绝对值函数,通过多个偏函数得到整个函数,每个函数根据不同情况调用
def abs(x :Int):Int = (positiveAbs orElse negativeAbs orElse zeroAbs) (x)

// 结果 5
println(abs(-5))

3. 偏应用函数

偏应用函数(Partial Applied Function)也叫部分应用函数,指一个函数有n个参数, 而我们为其提供少于n个参数, 那就得到了一个部分应用函数,类似于柯里化(把接受多个参数的函数变换成接受一个单一参数)。

1
2
3
4
5
6
7
8
9
10
11
12
scala> def add(x:Int,y:Int,z:Int) = x+y+z
add: (x: Int, y: Int, z: Int)Int

scala> def addX = add(1,:Int,:Int) // x 已知
addX: (Int, Int) => Int
scala> addX(2,3)
res1: Int = 6

scala> def addXAndY = add(10,100,_:Int) // x 和 y 已知
addXAndY: Int => Int
scala> addXAndY(1)
res2: Int = 111