ptrlaszlo
ptrlaszlo

Reputation: 337

An object with unapply working in middle of a case statement

scala> object Test {
         def unapply[L,R](v: (L, R)) = Some(v)
       }
defined object Test

scala> (1, 2) match {
         case 1 Test 2 => println("First")
         case Test((1, 2)) => println("Second")
         case _ => println("Third")
       }
First

Could somebody explain why is the first case working with the object in between the two values of the tuple?

Upvotes: 5

Views: 108

Answers (2)

Suma
Suma

Reputation: 34423

Infix operation patterns - see The Neophyte's Guide to Scala Part 1: Extractors:

If you followed the Scala course at Coursera, you learned that you can destructure lists and streams in a way that is akin to one of the ways you can create them, using the cons operator, :: or #::, respectively:

val xs = 58 #:: 43 #:: 93 #:: Stream.empty
xs match {
  case first #:: second #:: _ => first - second
  case _ => -1
}

Maybe you have wondered why that is possible. The answer is that as an alternative to the extractor pattern notation we have seen so far, Scala also allows extractors to be used in an infix notation. So, instead of writing e(p1, p2), where e is the extractor and p1 and p2 are the parameters to be extracted from a given data structure, it’s always possible to write p1 e p2

... our PremiumUser extractor could also be used in a pattern that reads name PremiumUser score. However, this is not something you would do in practice. Usage of infix operation patterns is only recommended for extractors that indeed are supposed to read like operators, which is true for the cons operators of List and Stream, but certainly not for our PremiumUser extractor.

Upvotes: 2

Marth
Marth

Reputation: 24812

From the Scala Specifications 8.1.10:

Infix Operation Patterns
An infix operation pattern p;op;q is a shorthand for the constructor or extractor pattern op(p,q).

So

case 1 Test 2 => println("First")

is rewritten to

case Test(1, 2) => println("First")

You can actually see this in the REPL by adding //print at the end of the line and pressing <tab> twice:

scala> (1, 2) match { case 1 Test 2 => println("First") } //print
   scala.Tuple2.apply[Int, Int](1, 2) match {
     case $line10.$read.$iw.$iw.Test(1, 2) => scala.Predef.println("First")
   } // : Unit

Upvotes: 5

Related Questions