Variable binding oddity

View: New views
4 Messages — Rating Filter:   Alert me  

Variable binding oddity

by csar :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hi,

can someone explain this to me:

scala> import xml._
import xml._

scala> val a:Node = <a/>
a: scala.xml.Node = <a></a>

scala> a match {case e:Elem => e}
res0: scala.xml.Elem = <a></a>

scala> a match {case e @ Elem(_,_,_,_,_*) => e}
res1: scala.xml.Node = <a></a>

Why Node and not Elem?

This works as expected:

scala> class Foo(a:Int)
defined class Foo

scala> case class Bar(i:Int) extends Foo(-i)
defined class Bar

scala> val f:Foo=Bar(1)
f: Foo = Bar(1)

scala> f match {case b:Bar => b}
res6: Bar = Bar(1)

scala> f match {case b @ Bar(_) => b}
res7: Bar = Bar(1)

-Carsten

Re: Variable binding oddity

by Kevin Wright-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

It's using an extractor, not a case class

=> http://www.scala-lang.org/docu/files/api/scala/xml/Elem$object.html

unapplySeq on the Elem object is defined to accept a node, so you can write:

val node : Node = ...

node match {
case Elem(...) => ...
}




On Tue, Jul 7, 2009 at 1:12 PM, Carsten Saager <csaager@...> wrote:
Hi,

can someone explain this to me:

scala> import xml._
import xml._

scala> val a:Node = <a/>
a: scala.xml.Node = <a></a>

scala> a match {case e:Elem => e}
res0: scala.xml.Elem = <a></a>

scala> a match {case e @ Elem(_,_,_,_,_*) => e}
res1: scala.xml.Node = <a></a>

Why Node and not Elem?

This works as expected:

scala> class Foo(a:Int)
defined class Foo

scala> case class Bar(i:Int) extends Foo(-i)
defined class Bar

scala> val f:Foo=Bar(1)
f: Foo = Bar(1)

scala> f match {case b:Bar => b}
res6: Bar = Bar(1)

scala> f match {case b @ Bar(_) => b}
res7: Bar = Bar(1)

-Carsten


Re: Variable binding oddity

by Daniel Sobral :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Kevin explanation is correct, but I'll expand on it.
 
When you write e: Elem, you are saying "e" of type "Elem", and that type is explicitly assigned to e.
 
When you write e @ Elem(_._,_,_,_ : _*), what actually happen is the following:
 
1. See if object Elem has n unapply or unapplySeq method.
2. If it has, see if it's input parameter is of a type compatible with "a".
3. If it has, call Elem.unapply(a) or Elem.unapplySeq(a).
4. Check that the return result is Some(...).
5. Check that the return result can be assigned to the parameters you are passing.
6. Assign "a" to "e", making "e" of the same type as that of the input parameter of Elem.unapplySeq (which, btw, is Node).
 
If any of the above steps fail, the case statement fails. To be a bit more complete, note that an object's unapply method in step tree can also return a Boolean instead of an Option, meaning there is no parameters being extracted. Also, in step 5 you go back to step 1 for each of the received parameters, if needed.

On Tue, Jul 7, 2009 at 9:12 AM, Carsten Saager <csaager@...> wrote:
Hi,

can someone explain this to me:

scala> import xml._
import xml._

scala> val a:Node = <a/>
a: scala.xml.Node = <a></a>

scala> a match {case e:Elem => e}
res0: scala.xml.Elem = <a></a>

scala> a match {case e @ Elem(_,_,_,_,_*) => e}
res1: scala.xml.Node = <a></a>

Why Node and not Elem?

This works as expected:

scala> class Foo(a:Int)
defined class Foo

scala> case class Bar(i:Int) extends Foo(-i)
defined class Bar

scala> val f:Foo=Bar(1)
f: Foo = Bar(1)

scala> f match {case b:Bar => b}
res6: Bar = Bar(1)

scala> f match {case b @ Bar(_) => b}
res7: Bar = Bar(1)

-Carsten



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.

Re: Variable binding oddity

by Kevin Wright-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Yeah, sorry about the sort reply, I'm at work :)

I guess that if it was a real problem, then we could always overload unapplyseq to explicitly accept an Elem


On Tue, Jul 7, 2009 at 2:01 PM, Daniel Sobral <dcsobral@...> wrote:
Kevin explanation is correct, but I'll expand on it.
 
When you write e: Elem, you are saying "e" of type "Elem", and that type is explicitly assigned to e.
 
When you write e @ Elem(_._,_,_,_ : _*), what actually happen is the following:
 
1. See if object Elem has n unapply or unapplySeq method.
2. If it has, see if it's input parameter is of a type compatible with "a".
3. If it has, call Elem.unapply(a) or Elem.unapplySeq(a).
4. Check that the return result is Some(...).
5. Check that the return result can be assigned to the parameters you are passing.
6. Assign "a" to "e", making "e" of the same type as that of the input parameter of Elem.unapplySeq (which, btw, is Node).
 
If any of the above steps fail, the case statement fails. To be a bit more complete, note that an object's unapply method in step tree can also return a Boolean instead of an Option, meaning there is no parameters being extracted. Also, in step 5 you go back to step 1 for each of the received parameters, if needed.

On Tue, Jul 7, 2009 at 9:12 AM, Carsten Saager <csaager@...> wrote:
Hi,

can someone explain this to me:

scala> import xml._
import xml._

scala> val a:Node = <a/>
a: scala.xml.Node = <a></a>

scala> a match {case e:Elem => e}
res0: scala.xml.Elem = <a></a>

scala> a match {case e @ Elem(_,_,_,_,_*) => e}
res1: scala.xml.Node = <a></a>

Why Node and not Elem?

This works as expected:

scala> class Foo(a:Int)
defined class Foo

scala> case class Bar(i:Int) extends Foo(-i)
defined class Bar

scala> val f:Foo=Bar(1)
f: Foo = Bar(1)

scala> f match {case b:Bar => b}
res6: Bar = Bar(1)

scala> f match {case b @ Bar(_) => b}
res7: Bar = Bar(1)

-Carsten



--
Daniel C. Sobral

Something I learned in academia: there are three kinds of academic reviews: review by name, review by reference and review by value.