2016-03-20 14 views
3

Ниже приведены две частичные функции, которые, как ожидается, будут выполнять задачи, но определяются различными способами.прямое применение функции подъема не дает ожидаемой функции

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) 

Почему проходит нуль в lift2 дает MatchError, когда определение как Lift1 и lift2 такое же?

+0

Jeez, ребята, комментарий _the difference_. Я потратил 10 минут, глядя на пустое пространство между 'if' и' s (', пытаясь понять, почему это важно. (Подскажите для всех остальных, это' '' после объявления типа. – Malvolio

ответ

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

Так оборачивает нормальную функцию в частичной функции, определенной на всей области. И именно поэтому, когда вы поднимаете, вы получите исключение - потому что внутри по-прежнему нормально не-поднятый частичная функция, которая не определена

0

Почему проходящее нуль в 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, как вы видите.