Freewind
Freewind

Reputation: 198218

Difference of pattern matching for "::(a,b)" and "List(a,b)"

To use :: to pattern match a list:

val ::(a, tail) =  List(1,2,3)

// a: Int = 1
// tail: List[Int] = List(2, 3)

But with List:

val List(a, tail) = List(1,2,3)

// match error

I tried to figure out why the later one can't be matched, but without lucky.

I see in the abstract class SeqFactory, there is a unapplySeq method:

def unapplySeq[A](x: CC[A]): Some[CC[A]] = Some(x)

But when x is List[Int], the return value is still Some[List[Int]], I can't find where the magic is

Upvotes: 3

Views: 81

Answers (1)

Electric Coffee
Electric Coffee

Reputation: 12104

The reason for this is quite simple.

List(1,2,3) is a list containing 3 elements: [1,2,3], similarly List(head, tail) is a list containing 2 elements: [head, tail]. It is not however a head and its tail.

scala> val hd :: tl = List(1,2,3) // val hd :: tl works the same as ::(hd, tl)
hd: Int = 1
tl: List[Int] = List(2,3)

scala> val List(a,b,c) = List(1,2,3)
a: Int = 1
b: Int = 2
c: Int = 3

So when you want to unapply a list using List you need to match the exact number of items in said list. Otherwise use the more historical :: operator to get the head and the tail

Upvotes: 3

Related Questions