Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pattern Matching - @ versus :?

Tags:

scala

Given:

case object A

What's the difference, if any, between the @ and : in:

def f(a: A.type): Int = a match {
   case aaa @ A => 42
}

and

def f(a: A.type): Int = a match {
   case aaa : A.type => 42
}
like image 600
Kevin Meredith Avatar asked Mar 27 '17 13:03

Kevin Meredith


2 Answers

The first one @ uses an extractor to do the pattern matching while the second one : requires the type - that's why you need to pass in A.type there.

There's actually no difference between them in terms of matching. To better illustrate the difference between @ and : we can look at a simple class, which doesn't provide an extractor out of the box.

class A

def f(a: A) = a match {
  case _ : A => // works fine
  case _ @ A => // doesn't compile because no extractor is found
}
like image 107
Andrei T. Avatar answered Sep 20 '22 22:09

Andrei T.


In this very specific case, almost nothing is different. They will both achieve the same results.

Semantically, case aaa @ A => 42 is usage of pattern binding where we're matching on the exact object A, and case aaa : A.type => 42 is a type pattern where we want a to have the type A.type. In short, type versus equality, which doesn't make a difference for a singleton.

The generated code is actually slightly different. Consider this code compiled with -Xprint:patmat:

def f(a: A.type): Int = a match {
  case aaa @ A => 42
  case aaa : A.type => 42
}

The relevant code for f shows that the two cases are slightly different, but will not produce different results:

def f(a: A.type): Int = {
  case <synthetic> val x1: A.type = a;
  case6(){
    if (A.==(x1))  // case aaa @ A
      matchEnd5(42)
    else
      case7()
  };
  case7(){
    if (x1.ne(null)) // case aaa: A.type
      matchEnd5(42)
    else
      case8()
  };
  case8(){
    matchEnd5(throw new MatchError(x1))
  };
  matchEnd5(x: Int){
    x
  }
}

The first case checks equality, where the second case only checks that the reference is not null (we already know the type matches since the method parameter is the singleton type).

like image 40
Michael Zajac Avatar answered Sep 17 '22 22:09

Michael Zajac