Operador Scala @

Respostas:

179

Ele permite vincular um padrão correspondente a uma variável. Considere o seguinte, por exemplo:

val o: Option[Int] = Some(2)

Você pode extrair facilmente o conteúdo:

o match {
  case Some(x) => println(x)
  case None =>
}

Mas e se você não quisesse o conteúdo de Some, mas a opção em si? Isso seria realizado com isso:

o match {
  case x @ Some(_) => println(x)
  case None =>
}

Observe que @pode ser usado em qualquer nível, não apenas no nível superior da correspondência.

Daniel C. Sobral
fonte
5
Onde na documentação eu encontraria essa resposta? Tenho a sensação de que há outras coisas boas enterradas lá também. :)
Jim Barrows
1
@ Jim Scala Reference, 8.1. 8.12, especificamente, embora eu não saiba de onde veio o "como sempre" - e 8.12 falam apenas do padrão de expressão regular ( _*). Mas talvez isso tenha sido esclarecido em uma versão mais recente da especificação.
Daniel C. Sobral
16
Eu acrescentaria que você provavelmente não usaria @com Some(_), mas se quiser corresponder ao conteúdo do Some, mas ainda se referir ao próprio, por exemplo case x @ Some(7) => println(x). Na minha interpretação, case x @ Some(_)é apenas uma versão mais detalhada do case x: Some.
Theo
2
Isso também é abordado em "Ligação variável" na Seção 15.2 de "Programação no Scala - 2ª Edição" e usado novamente na seção 26.3 (o capítulo sobre extratores).
Shaun the Sheep
@Theo case x: Somenão funciona por si só. Você tem que usar case x: Some[_], o que não é menos detalhado
Luigi Plinge
74

@pode ser usado para vincular um nome a um padrão ou subpadrão correspondido com êxito. Os padrões podem ser usados ​​na correspondência de padrões, no lado esquerdo da entrada <-para compreensão e na atribuição de desestruturações.

scala> val d@(c@Some(a), Some(b)) = (Some(1), Some(2))
d: (Some[Int], Some[Int]) = (Some(1),Some(2))
c: Some[Int] = Some(1)
a: Int = 1
b: Int = 2

scala> (Some(1), Some(2)) match { case d@(c@Some(a), Some(b)) => println(a, b, c, d) }
(1,2,Some(1),(Some(1),Some(2)))

scala> for (x@Some(y) <- Seq(None, Some(1))) println(x, y)
(Some(1),1)

scala> val List(x, xs @ _*) = List(1, 2, 3) 
x: Int = 1
xs: Seq[Int] = List(2, 3)
retrônimo
fonte
10

Quando a correspondência de padrões variable @ patternliga a variável ao valor correspondente ao padrão, se o padrão corresponder. Nesse caso, isso significa que o valor de xestará Some(Nil)nessa cláusula de caso.

sepp2k
fonte
9

Permite corresponder ao nível superior de um padrão. Exemplo:

case x @ "three" => assert(x.equals("three"))
case x @ Some("three") => assert(x.get.equals("three")))
case x @ List("one", "two", "three") => for (element <- x) { println(element) }
Mitch Blevins
fonte
6
Não apenas de nível superior.
Daniel C. Sobral
2

Ele define o valor de xpara o padrão que corresponde. No seu exemplo, xseria , portanto, Some(Nil)(como você pode determinar a partir de uma chamada para println )

oxbow_lakes
fonte
1
Condene a incapacidade dos iPhones de renderizar um backtick!
precisa saber é o seguinte