3

Below are the two partial function that are expected to perform sme tasks but defined in diffrent ways.

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)

Why passing null to lift2 gives MatchError, when the definition of both lift1 and lift2 is same?

4

2 回答 2

1

当 lift1 和 lift2 的定义相同时,为什么将 null 传递给 lift2 会产生 MatchError?

它们的定义不同。当你定义:

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)
});

它实际上将 a 包裹Function1在一个偏函数内部。因此,当您调用 时pf2.lift(null),它会在内部调用Function1,从而导致MatchError您看到的 a 。

于 2016-03-20T08:16:02.637 回答
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) }

所以它将一个普通函数包装成在所有域上定义的部分函数。这就是为什么当你提升时,你会收到异常 - 因为 inside 仍然是一个正常的未提升的部分函数,​​没有定义

于 2016-03-20T07:48:42.117 回答