Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between unapply and unapplySeq?

Why does Scala have both unapply and unapplySeq? What is the difference between the two? When should I prefer one over the other?

like image 613
Dan Burton Avatar asked Nov 26 '11 22:11

Dan Burton


People also ask

What is the difference between unapply and apply when would you use them?

Whereas the apply method is like a constructor which takes arguments and creates an object, the unapply takes an object and tries to give back the arguments. This is most often used in pattern matching and partial functions. The apply method creates a CustomerID string from a name .

What is use of Unapply method in Scala?

The unapply method breaks the arguments as specified and returns firstname object into an extractor . It returns a pair of strings if as an argument, the first name and last name is passed else returns none. Example : Scala.


2 Answers

Without going into details and simplifying a bit:

For regular parameters apply constructs and unapply de-structures:

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 }  

For repeated parameters, apply constructs and unapplySeq de-structures:

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

Note that in that second case, repeated parameters are treated like a Seq and the similarity between A* and _*.

So if you want to de-structure something that naturally contains various single values, use unapply. If you want to de-structure something that contains a Seq, use unapplySeq.

like image 107
huynhjl Avatar answered Sep 23 '22 11:09

huynhjl


Fixed-arity vs. variable arity. Pattern Matching in Scala (pdf) explains it well, with mirroring examples. I also have mirroring examples in this answer.

Briefly:

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 

So, which do you think is exhibited in the following example?

scala> List(1) match { case List(x) => x } res3: Int = 1 
like image 36
Julian Fondren Avatar answered Sep 23 '22 11:09

Julian Fondren