Follow me on GitHub

Scala | case 语句究竟是什么类型?

Scala | case 关键字的 4 种用法 一文中我提到 case 语句可以创建偏函数字面值,实际上这种说法并不完全正确。

Scala 中 case 语句形如:

1
{ case p1 => e1; case p2 => e2; ...; case pn => en }

实际上,仅给定 case 语句本身,我们只能确定它是一个 匿名函数,但 无法 确定该匿名函数的具体类型,根据 case 语句所处上下文对它的期待,它可以是:

  • 普通函数(FunctionN)的匿名值
  • 偏函数(PartialFunction)的匿名值

普通函数

Seq.map 的参数类型为 A => BFunction1[A, B]),因此若用 case 语句作为其实参,则 case 语句类型就是 A => B

1
2
3
4
// List(2, 4, 6)
Seq(1, 2, 3).map {
case n ⇒ n * 2
}

该场景下 { case n => n * 2 } 将被 Scala 编译器展开成 Function1[Int, Int] 实例:

1
2
3
4
5
new Function[Int, Int] {
override def apply(v1: Int) = v1 match {
case n ⇒ n * 2
}
}

偏函数

Seq.collect 的参数类型为 PartialFunction[A, B],因此若用 case 语句作为其实参,则 case 语句类型为 PartialFunction[A, B]

1
2
3
4
// List(2, 4, 6)
Seq(1, 2, 3, "A").collect {
case n: Int ⇒ n * 2
}

该场景下 { case n: Int => n * 2 } 将被 Scala 编译器展开为 PartialFunction[Int, Int] 实例:

1
2
3
4
5
6
7
8
9
10
new PartialFunction[Int, Int] {
override def isDefinedAt(x: Int) = x match {
case _: Inttrue
case _ ⇒ false
}

override def apply(v1: Int) = v1 match {
case n: Int ⇒ n * 2
}
}

参考: