В чем разница между неприменимым и неиспользованным Seq? - PullRequest
35 голосов
/ 27 ноября 2011

Почему у Scala есть unapply и unapplySeq?Какая разница между двумя?Когда я должен предпочесть одно другому?

Ответы [ 3 ]

31 голосов
/ 27 ноября 2011

Не вдаваясь в детали и немного упрощая:

Для обычных параметров apply конструкции и unapply деструктуры:

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 } 

Для повторяющихся параметров apply конструкциии unapplySeq де-структуры:

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 @ _*) => ... } 

Обратите внимание, что во втором случае повторяющиеся параметры обрабатываются как Seq и сходство между A* и _*.

Поэтому, если вы хотите деструктурировать что-то, что естественно содержит различные отдельные значения, используйте unapply.Если вы хотите деструктурировать то, что содержит Seq, используйте unapplySeq.

18 голосов
/ 27 ноября 2011

Фиксированная арность против переменной арности. Pattern Matching in Scala (pdf) объясняет это хорошо, с примерами зеркального отражения.У меня также есть примеры зеркального отражения в этом ответе .

Коротко:

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

Итак, что, по вашему мнению, представлено в следующем примере?

scala> List(1) match { case List(x) => x }
res3: Int = 1
0 голосов
/ 27 апреля 2019

Некоторые примеры:

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)

...