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

Sta*_*n L 3 scala partialfunction

Apologies if this is obvious but I am new to scala and I am getting two unexpected behaviors with the following code:

Seq(1, "a", 2, "b") map { 
    case i: Int => i+1
}
Run Code Online (Sandbox Code Playgroud)

1) I would have expected to get back a collection where the strings are unchanged and the numbers are incremented by 1 but instead I get an error.

2) I believe the case i: Int => i + 1 syntax represents a partial function which is defined for Ints. But it seems map takes a total function, so why does this even compile? Wouldn't it be better for the compiler to help me out? It is always better to move runtime exceptions to compile time exceptions.

jwv*_*wvh 6

map()不会将部分函数用作传递的参数,但collect()会这样做。

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

请注意,未为部分函数定义的输入是如何不传递而是被丢弃的。您不希望删除的内容需要一个处理程序,即使它只是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)
Run Code Online (Sandbox Code Playgroud)

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

值得注意的是,在处理部分函数时...

呼叫者有责任在致电isDefinedAt之前致电apply...

因此,我们可以得出结论,那就是这样collect()做,而map()不是。

  • @StanL`map`不检查`isDefinedAt`,因为`isDefinedAt`只为部分函数定义。由于`map`接受常规函数(并且仅接受部分函数,​​因为它们是常规函数的子类型),因此它实际上无法调用`isDefinedAt`。map仅用于与为列表中的所有值定义的函数一起使用。我认为您真正想问的是*为什么*部分函数是常规函数的子类型,其原因是如果您不能使用`{case ... => ... }`语法和`map`等。 (3认同)