下面是两个部分函数,它们可以执行sme任务,但是以不同的方式定义。
val pf1 : PartialFunction[String, String] = {
case s : String if (s != null) => s.toUpperCase()
}
//> pf1 : PartialFunction[String,String] = <function1>
val lift1 = pf1.lift
//> lift1 : String => Option[String] = <function1>
val d1 = lift1(null)
//> d1 : Option[String] = None
val d2 = lift1("hello world")
//> d2 : Option[String] = Some(hello world)
val pf2 = PartialFunction[String, String] {
case s : String if(s != null) => s.toUpperCase()
}
//> pf2 : PartialFunction[String,String] = <function1>
val lift2 = pf2.lift
//> lift2 : String => Option[String] = <function1>
val d3 = lift2(null)
//> scala.MatchError: null
val d4 = lift2("hii")
//> d4 : Option[String] = Some(hii)
为什么当lift1和lift2的定义相同时,将null传递给lift2会产生MatchError?
答案 0 :(得分:1)
如果您查看PartialFunction.apply
,您会发现它与您预期的有所不同:
/** Converts ordinary function to partial one
* @since 2.10
*/
def apply[A, B](f: A => B): PartialFunction[A, B] = { case x => f(x) }
因此它将正常函数包装到在所有域上定义的部分函数中。这就是为什么当你举起时,你会收到异常 - 因为内部仍然是一个正常的未被提升的部分功能,这是未定义的
答案 1 :(得分:1)
为什么将null传递给lift2会给出MatchError,当定义时 lift1和lift2都一样吗?
它们的定义不一样。定义时:
val pf1: PartialFunction[String, String] = {
case s : String if (s != null) => s.toUpperCase()
}
编译器创建PartialFunction
,如下所示:
this.pf1 = ({
new <$anon: Function1>()
}: PartialFunction);
但是当你宣布pf2
时这样:
val pf2 = PartialFunction[String, String] {
case s : String if(s != null) => s.toUpperCase()
}
你实际上告诉编译器“请把这个Function1
传递给PartialFunction.apply
。这就是编译器这样做的原因:
this.pf2 = scala.PartialFunction.apply({
(new <$anon: Function1>(): Function1)
});
实际上将Function1
包含在部分函数中。因此,当您致电pf2.lift(null)
时,它会在内部调用Function1
,导致您看到MatchError
。