case classes e pattern matching

5 views
Skip to first unread message

Rafael Afonso

unread,
Oct 20, 2009, 8:55:55 PM10/20/09
to scala-br
Olá:

Quando tentei rodar o código abaixo:

case class ClasseA
case object object1 extends ClasseA
case object object2 extends ClasseA
case object object3 extends ClasseA

val obj = object2

obj match {
case object1 => println("obj 1")
case object2 => println("obj 2")
case object3 => println("obj 3")
}

O compilador retornou o seguinte:

<console>:13: error: unreachable code
case object2 => println("obj 2")
^
<console>:14: error: unreachable code
case object3 => println("obj 3")

Afinal de contas, o que fiz de errado aqui? O que ficou faltando?

Grato,

Rafael U. C. Afonso

Rafael de F. Ferreira

unread,
Oct 20, 2009, 9:30:13 PM10/20/09
to scal...@googlegroups.com
Em um pattern, scala considera tudo que começa com letra minúscula
como uma variável. Então o seu match é o mesmo que:

obj match {
case x => println("obj 1")
case y => println("obj 2")
case z => println("obj 3")
}

Como essas variáveis não especificam mais nenhuma restrição, o
primeiro case vai sempre ser selecionado e os outros ignorados. A
solução é usar a convenção de nomear seus tipos com a primeira letra
maiúscula:

case object Object1 extends ClasseA

IIRC, um workaround seria expressar o nome do tipo entre backticks:


obj match {
case `object1` => println("obj 1")

case `object2`=> ....
}


--
Rafael de F. Ferreira.
http://www.rafaelferreira.net/

2009/10/20 Rafael Afonso <rafael...@gmail.com>:

Alexei Barbosa de Aguiar

unread,
Oct 20, 2009, 9:56:45 PM10/20/09
to scal...@googlegroups.com
    Estás sabendo um bocado, hein ? :-)  Essa foi bem específica.

Rafael de F. Ferreira escreveu:
-- 
Alexei Barbosa de Aguiar
Verde Tecnologia
+55(85)8776.0801
+55(85)3474.5040
Skype: alexeiaguiar

Rafael de F. Ferreira

unread,
Oct 20, 2009, 10:53:23 PM10/20/09
to scal...@googlegroups.com
Valeu, mas nem tanto, é que esse problema já me mordeu antes.

--
Rafael de F. Ferreira.
http://www.rafaelferreira.net/

2009/10/20 Alexei Barbosa de Aguiar <ale...@verde.com.br>:

Rafael Afonso

unread,
Oct 21, 2009, 9:15:38 PM10/21/09
to scala-br
Olá:

Desculpem a minha demora mas só agora consegui experimentar a
sugestão. Renomeei os objects com a primeira letra maiúscula.
Entretanta afora o problema é outro. Segue-se o script:

case class ClasseA
case object Object1 extends ClasseA
case object Object2 extends ClasseA
case object Object3 extends ClasseA

val obj = Object2

obj match {
case Object1 => println("obj 1")
case Object2 => println("obj 2")
case Object3 => println("obj 3")
}

O retorno o shell foi o seguinte:

<console>:12: error: pattern type is incompatible with expected type;
found : object Object1
required: object Object2
case Object1 => println("obj 1")
^
<console>:14: error: pattern type is incompatible with expected type;
found : object Object3
required: object Object2
case Object3 => println("obj 3")

Achei estranho, pois o pattern matching não deveria "descobrir" a qual
classe obj pertenceria? Enquanto estava escrevendo esta mensagem tive
uma idéia e resolvi experimentar isto aqui:

case class ClasseA()
case object Object1 extends ClasseA
case object Object2 extends ClasseA
case object Object3 extends ClasseA

def funcao(obj: ClasseA) = obj match {
case Object1 => println("obj 1")
case Object2 => println("obj 2")
case Object3 => println("obj 3")
}

val obj = Object2
funcao(obj)

E finalmente obtive a resposta esperada.
Então resolvi refazer o primeiro exemplo mas desta vez explicitando a
classe de obj:

case class ClasseA()
case object Object1 extends ClasseA
case object Object2 extends ClasseA
case object Object3 extends ClasseA

val obj:ClasseA = Object2

obj match {
case Object1 => println("obj 1")
case Object2 => println("obj 2")
case Object3 => println("obj 3")
}

E agora sim deu certo.


On 21 out, 00:53, "Rafael de F. Ferreira" <rafael...@gmail.com> wrote:
> Valeu, mas nem tanto, é que esse problema já me mordeu antes.
>
> --
> Rafael de F. Ferreira.http://www.rafaelferreira.net/
>
> 2009/10/20 Alexei Barbosa de Aguiar <ale...@verde.com.br>:
>
> >     Estás sabendo um bocado, hein ? :-)  Essa foi bem específica.
>
> > Rafael de F. Ferreira escreveu:
>
> > Em um pattern, scala considera tudo que começa com letra minúscula
> > como uma variável. Então o seu match é o mesmo que:
>
> > obj match {
> >        case x => println("obj 1")
> >        case y  => println("obj 2")
> >        case z => println("obj 3")
> > }
>
> > Como essas variáveis não especificam mais nenhuma restrição, o
> > primeiro case vai sempre ser selecionado e os outros ignorados. A
> > solução é usar a convenção de nomear seus tipos com a primeira letra
> > maiúscula:
>
> > case object Object1 extends ClasseA
>
> > IIRC, um workaround seria expressar o nome do tipo entre backticks:
> > obj match {
> >   case `object1` => println("obj 1")
> >   case `object2`=> ....
> > }
>
> > --
> > Rafael de F. Ferreira.
> >http://www.rafaelferreira.net/
>
> > 2009/10/20 Rafael Afonso <rafael.afo...@gmail.com>:

Rafael de F. Ferreira

unread,
Oct 22, 2009, 12:27:55 AM10/22/09
to scal...@googlegroups.com
> Achei estranho, pois o pattern matching não deveria "descobrir" a qual
> classe obj pertenceria? Enquanto estava escrevendo esta mensagem tive
> uma idéia e resolvi experimentar isto aqui:

O compilador é esperto. Quando vc fez "val obj = Object2", ele deu à
variável obj o tipo Object2.type. Assim, na hora do pattern matching
ele já sabia que obj nunca poderia ser nem Object1 nem Object3.

Reply all
Reply to author
Forward
0 new messages