模式匹配,“::”unapply混乱

时间:2013-07-23 17:00:27

标签: scala

我是斯卡拉的新手,在研究模式匹配部分时,我感到困惑。

val hd::tail = List(1,2,3,4,5)

执行此代码后,hd将为Int = 1,tail将为List [Int] = List(2,3,4,5)。 这段代码等于:

val ::(hd,tail) = List(1,2,3,4,5)

我了解到这段代码是模式匹配,实际上它调用了unapply方法。 但是当我以这种方式编写代码时,编译错误:

val result = ::.unapply(List(1,2,3,4,5))

它表示方法参数类型不匹配。 “::”的unapply方法需要“:: [?]”

有谁知道原因?

2 个答案:

答案 0 :(得分:4)

类型不匹配错误是因为::.unapply采用::[T]的实例而不是更通用类型List[T]的实例。 Scala会根据实际类型自动添加匹配项。 换句话说,我的理解是当你这样做时:

val list = List(1,2,3,4,5)
val hd::tail = list

编译器生成类似于此的东西:

val list = List(1,2,3,4,5)
val (hd, tail) = 
  ::.unapply(
    // First match to test against input type
    // (necessary as the static type of `list` is `List[Int]`
    // so we don't know until runtime if it is an instance of `::[Int]`
    // or an instance of `Nil`)
    list match { 
      case nonEmptyList: ::[Int] => nonEmptyList 
      case _ => throw new MatchError 
    }
  ) match { // Second match to test against result of `::`.unapply
    case Some( result ) => result
    case _ => throw new MatchError 
  }

答案 1 :(得分:1)

您拥有的方法签名不正确。 ::是一个案例类,因此取消应用::的实例。这里有一些更接近你可能正在寻找的东西,虽然我通常不会在代码中调用unapply,因为它是在模式匹配场景中完成的:

  //Note the type returned by unapply
  val unappliedOption:Option[(Int, List[Int])] = ::.unapply(::(1, List(2, 3, 4, 5)))

  val (hd, tail) = unappliedOption.getOrElse((1, Nil))

在模式匹配中unapply会自动为您调用。另请注意,::是非空列表,但仍会返回option。因此,对于List的实例,我们有两个选项::Nil

  List(1, 2, 3, 4, 5) match {
    case hd :: tail => println(hd, tail) // calls ::.unapply and returns hd tail if the option is Some
    case hd => println(hd) //Default case Nil
  }