Scala unapply和Unplyseq之间有什么区别?

Scala unapply和Unplyseq之间有什么区别?,scala,pattern-matching,unapply,Scala,Pattern Matching,Unapply,为什么Scala同时具有unapply和unplyseq?这两者的区别是什么?什么时候我应该选择一种而不是另一种?固定算术与可变算术。通过镜像示例很好地解释了这一点。我在中也有镜像示例 简而言之: object Sorted { def unapply(xs: Seq[Int]) = if (xs == xs.sortWith(_ < _)) Some(xs) else None } object SortedSeq { def unapplySeq(xs: Seq[In

为什么Scala同时具有
unapply
unplyseq
?这两者的区别是什么?什么时候我应该选择一种而不是另一种?

固定算术与可变算术。通过镜像示例很好地解释了这一点。我在中也有镜像示例

简而言之:

object Sorted {
  def unapply(xs: Seq[Int]) =
    if (xs == xs.sortWith(_ < _)) Some(xs) else None
}

object SortedSeq {
  def unapplySeq(xs: Seq[Int]) =
    if (xs == xs.sortWith(_ < _)) Some(xs) else None
}

scala> List(1,2,3,4) match { case Sorted(xs) => xs }
res0: Seq[Int] = List(1, 2, 3, 4)
scala> List(1,2,3,4) match { case SortedSeq(a, b, c, d) => List(a, b, c, d) }
res1: List[Int] = List(1, 2, 3, 4)
scala> List(1) match { case SortedSeq(a) => a }
res2: Int = 1

不深入细节,不做任何简化:

对于常规参数
apply
构造和
unapply
de结构:

object S {
  def apply(a: A):S = ... // makes a S from an A
  def unapply(s: S): Option[A] = ... // retrieve the A from the S
}
val s = S(a)
s match { case S(a) => a } 
object M {
  def apply(a: A*): M = ......... // makes a M from an As.
  def unapplySeq(m: M): Option[Seq[A]] = ... // retrieve the As from the M
}
val m = M(a1, a2, a3)
m match { case M(a1, a2, a3) => ... } 
m match { case M(a, as @ _*) => ... } 
对于重复参数,
apply
构造和
unplyseq
de结构:

object S {
  def apply(a: A):S = ... // makes a S from an A
  def unapply(s: S): Option[A] = ... // retrieve the A from the S
}
val s = S(a)
s match { case S(a) => a } 
object M {
  def apply(a: A*): M = ......... // makes a M from an As.
  def unapplySeq(m: M): Option[Seq[A]] = ... // retrieve the As from the M
}
val m = M(a1, a2, a3)
m match { case M(a1, a2, a3) => ... } 
m match { case M(a, as @ _*) => ... } 
请注意,在第二种情况下,重复参数被视为a
Seq
a*
.*
之间的相似性

因此,如果您想解构自然包含各种单一值的内容,请使用
unapply
。如果要对包含
Seq
的内容进行解构,请使用
unplyseq

一些示例:

scala> val fruit = List("apples", "oranges", "pears")
fruit: List[String] = List(apples, oranges, pears)

scala> val List(a, b, c) = fruit
a: String = apples
b: String = oranges
c: String = pears

scala> val List(a, b, _*) = fruit
a: String = apples
b: String = oranges

scala> val List(a, _*) = fruit
a: String = apples

scala> val List(a,rest @ _*) = fruit
a: String = apples
rest: Seq[String] = List(oranges, pears)

scala> val a::b::c::Nil = fruit
a: String = apples
b: String = oranges
c: String = pears

scala> val a::b::rest = fruit
a: String = apples
b: String = oranges
rest: List[String] = List(pears)

scala> val a::rest = fruit
a: String = apples
rest: List[String] = List(oranges, pears)


啊,谢谢!这是有道理的。从Haskell的角度来看,我认为在
列表(a,b,c)
上的匹配就像在
a::b::c::Nil
上的匹配一样,但Scala似乎没有这样做;相反,它使用了
List
unplyseq
方法。这个答案中提到的文章可以在这里找到:@dan Scala可以按照您期望的方式匹配列表,方法是在::companion对象上使用unply方法。正如预期的那样,这只是将列表(或者更确切地说是一个::)分解为头和尾。请注意,这只适用于列表,不适用于任何序列。上面的纸张URL似乎已损坏。似乎现在可以在