直接应用提升功能不给出预期的功能

时间:2016-03-20 07:22:17

标签: scala lifting

下面是两个部分函数,​​它们可以执行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?

2 个答案:

答案 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