2

我是 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 方法需要一个 "::[?]"

有谁知道原因?

4

2 回答 2

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 
  }
于 2013-07-23T17:34:26.863 回答
1

您拥有的方法签名不正确。::是一个案例类,所以 unapply 需要一个::. 这里有一些更接近您可能正在寻找的东西,尽管通常我不会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
  }
于 2013-07-23T17:11:44.970 回答