模式匹配“ @”符号


70

给定此Person案例类:

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

...和这个实例

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

是否有理由偏爱此代码(带有@

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

...在以下?

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

也许我错过了的意义/力量@

Answers:


111

@当您还希望处理对象本身时,才包括。因此:

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

否则,将其包含在内没有任何实际意义。


3
您使用分号来引用对象本身。我想知道为什么不重复使用分号to refer the object itself
2015年

很高兴知道!在阅读此答案之前,我将这样写:case p: Person if p != bill => p.age
erdavila

@erdavila没有任何问题。在某些圈子中甚至可能更喜欢它。
麦迪

4
@Val我花了很多时间思考这个问题,直到最近才发现。这是因为冒号(不是分号)在类型上匹配,但是并非所有提取器都这样做。如果您创建了一个自定义提取器,并且嵌套在任何类型的另一个提取器中,则可能要引用该自定义提取器匹配的对象,但是自定义提取器可能不会是该对象类型的名称,因此冒号是不合适的。
2016年

1
有关使用不同语法进行模式匹配的含义的更多信息。检查:scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html了解更多信息
Christian Vielma,

13

关于上述答案的评论。

考虑这个案例类。

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

在进行模式匹配时。

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**

7
这种情况不需要@构造。你可以做case Employee(name, _, "scala") => name
GatesDA '18 -10-16

虽然并不一定需要第一行(根据先前的命令),但我非常感谢您提供的简化对比使我能够把握区别。即使在超过8年的Scala之后,这也足够了,我忘记了这个特定的事情是如何以及为什么起作用的。
chaotic3quilibrium
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.