80

Given this Person case class:

scala> case class Person(name: String, age: Int) {}
defined class Person

... and this instance

scala> val b = Person("Kevin", 100)
b: Person = Person(Kevin,100)

Is there a reason to prefer this code (with @)

scala> b match {
     |    case p @ Person(_, age) => println("age")
     |    case _ => println("none")
     | }
age

... over the following?

scala> b match {
     |    case Person(_, age) => println("age")
     |    case _ => println("none")
     | }
age

Perhaps I'm missing the meaning/power of @?

Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

2 Answers2

129

You only include the @ when you want to also deal with the object itself. Hence:

that match{
  case p @ Person(_, age) if p != bill => age
  case Person(_, age) => age - 15
  case _ => println("Not a person")
}

Otherwise, there's no real point in including it.

wheaties
  • 35,646
  • 15
  • 94
  • 131
  • 4
    You use semicolon for referring the object itself. I wonder why semicolon is not reused `to refer the object itself`? – Val May 28 '15 at 13:31
  • Good to know! Before reading this answer, I would write this way: `case p: Person if p != bill => p.age` – erdavila Dec 06 '16 at 17:36
  • @erdavila there's nothing wrong with that. It might even be prefered in some circles. – wheaties Dec 06 '16 at 17:39
  • 4
    @Val I spent a lot of time thinking about that and only recently figured it out. It's because the colon (not semicolon) matches on types, but not all extractors do this. If you make a custom extractor, and it's nested within another extractor of any type, you may want to reference the object that the custom extractor matched, yet the custom extractor likely wouldn't the name of the type of that object, so the colon would be inappropriate. – acjay Dec 19 '16 at 21:25
  • 1
    There's more about what it means to do pattern matching with different syntax. Check: http://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html for more information – Christian Vielma Mar 07 '17 at 10:27
16

Regarding the comments for the above answer.

Consider this case class.

case class Employee(name: String, id: Int, technology: String)

while doing pattern matching.

case e @ Employee(_, _, "scala") => e.name // matching for employees with only scala technology ... it works

case x: Employee => x.name // It also works

case e: Employee(_, _, "scala") => e.name // matching for employees with only scala technology ... **wont't work**
jwvh
  • 50,871
  • 7
  • 38
  • 64
Praveen L
  • 937
  • 6
  • 13
  • 7
    This scenario doesn't need the `@` construct. You can do `case Employee(name, _, "scala") => name` – GatesDA Oct 16 '18 at 19:03
  • 1
    While the first line is not precisely needed (per prior commrnt), I really appreciate your simplified contrast enabling me to grasp the distinction. This is just enough of an edge case, even after +8 years of Scala, I forget how and why this specific thing works. – chaotic3quilibrium Jul 20 '19 at 14:35