为什么提供部分函数来映射在运行时抛出而不是给出编译错误?

Why does providing a partial function to map throw at runtime rather than give a compile error?

抱歉,如果这很明显,但我是 scala 的新手,我使用以下代码遇到了两个意外行为:

Seq(1, "a", 2, "b") map { 
    case i: Int => i+1
}

1) 我本希望取回一个字符串未更改且数字递增 1 的集合,但我却收到错误消息。

2) 我相信 case i: Int => i + 1 语法表示为 Ints 定义的偏函数。但似乎 map 需要一个总函数,那么为什么它甚至可以编译呢?编译器帮我解决不是更好吗?将运行时异常移动到编译时异常总是更好。

尝试

Seq(1, "a", 2, "b") map {
  case i: Int => i + 1
  case any => any
}

输出

res0: Seq[Any] = List(2, a, 3, b)

Seq(1, "a", 2, "b") map { case i: Int => i + 1 }编译的原因是Seq(1, "a", 2, "b")的类型是Seq[Any]。另一方面,以下

Seq("a", "b").map { case i: Int => i + 1 }

给出编译器错误

scrutinee is incompatible with pattern type;
[error]  found   : Int
[error]  required: String
[error]   Seq("a", "b").map { case i: Int => i + 1 }

因为 Seq("a", "b") 的类型为 Seq[String]{ case i: Int => i + 1 } 的类型为 PartialFunction[Int, Int].

map() 不接受部分函数作为传递参数,但 collect() 接受。

Seq(1, "a", 2, "b") collect {
  case i: Int => i+1
}
//res0: Seq[Int] = List(2, 3)

注意没有为部分函数定义的输入是如何不通过而只是被丢弃的。你不想删除的东西需要一个处理程序,即使它只是一个 case _ => 默认处理程序。

Seq(1, "a", 2, "b", 'z') collect {
  case i: Int    => i+1        //increment ints
  case c: Char   => c.toUpper  //capitalize chars
  case s: String => s          //strings pass through
}
//res0: Seq[Any] = List(2, a, 3, b, Z)

当您将部分函数传递给 map() 时,编译器不会报错,因为 trait PartialFunction[-A, +B] extends (A) => B。换句话说,偏函数一种函数。

还值得注意的是,在处理偏函数时...

It is the responsibility of the caller to call isDefinedAt before calling apply...

所以我们可以得出结论,collect() 做到了,而 map() 没有。