В чем разница между шаблоном конструктора и шаблоном привязки переменных в выражении сопоставления scala?

В Scala я пытаюсь понять сопоставление с образцом, однако большинство шаблонов говорят сами за себя, но шаблон конструктора и шаблон привязки переменных кажутся мне запутанными. Я попробовал следующий пример из Programming Scala, 2ed

case class Address(street: String, city: String, country: String)
case class Person(name: String, age: Int, address: Address) 

object ScalaCaseDemoMain extends App{

    val alice   = Person("Alice",   25, Address("1 Scala Lane", "Chicago", "USA"))
    val bob     = Person("Bob",     29, Address("2 Java Ave.",  "Miami",   "USA"))
    val charlie = Person("Charlie", 32, Address("3 Python Ct.", "Boston",  "USA"))

    for (person <- Seq(alice, bob, charlie)) {
    person match {
        case p @ Person("Alice", 25, address) => println(s"Hi Alice! $p")
        case p @ Person("Bob", 29, a @ Address(street, city, country)) =>
        println(s"Hi ${p.name}! age ${p.age}, in ${a.city}")
        case p @ Person(name, age, _) =>
      println(s"Who are you, $age year-old person named $name? $p")
  }
}

    }

Я хочу знать, когда использовать шаблон конструктора

case Person("Alice", 25, address) => //some action here

и когда использовать шаблон привязки переменных

case p @ Person("Alice", 25, address) //some action here

Я всегда в замешательстве, когда дело доходит до сопоставления с образцом?


person optional    schedule 23.03.2016    source источник


Ответы (1)


Конструктор против экстрактора

Шаблон, который вы называете конструктором, в большинстве случаев называется Extractor или Deconstructor. Это похоже на обратный конструктор, как вы можете видеть по методу, который он вызывает unapply.

Если бы это произошло с правой стороны или за пределами pattern match, это было бы так, как вы отметили Constructor.

Отвечать

@ используется только в pattern matching для привязки деконструированного объекта к переменной. Его цель состоит в том, чтобы предоставить возможность поймать все выражение и по-прежнему иметь возможность использовать извлеченные значения на более поздних этапах.

Таким образом, всегда будет способ упорядочить код таким образом, чтобы вам не нужно было использовать @, но это могло сильно улучшить читабельность.

Пример

Пример использования @: вы хотите отправить письмо всем лицам по имени Алиса старше 21 года, но адрес не является важным критерием выбора.

case p @ Person("Alice", age, _) if age > 21 => storePersonForMailing(p)

Здесь совпадение с шаблоном ясно показывает ваше намерение, подчеркивая значения, которые вы используете для выбора, и, поскольку вам понадобится адрес позже для отправки почты, было бы не очень хорошей идеей отказаться от него.

person Andreas Neumann    schedule 23.03.2016
comment
Очень полезно, особенно пример - person optional; 23.03.2016