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

时间:2019-06-19 20:26:37

标签: scala partialfunction

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

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

1)我本来希望返回一个字符串不变且数字加1的集合,但我得到了一个错误。

2)我相信case i: Int => i + 1语法代表为Ints定义的部分函数。但是看来map需要一个总函数,那么为什么还要编译呢?编译器帮助我会更好吗?最好将运行时异常移至编译时间异常。

2 个答案:

答案 0 :(得分:6)

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。换句话说,部分功能 是一种功能。

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

  

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

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

答案 1 :(得分:3)

尝试

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]