- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Mutable XML and Elem apply/unapply conflict?
Sun, 2012-01-22, 20:40
There was a discussion on StackOverflow on ways to insert a node into an XML structure, which is immutable by nature (see http://stackoverflow.com/questions/2199040/scala-xml-building-adding-children-to-existing-nodes). One of the techniques proposed by Daniel Sobral looked basically like this:
class AddChildrenTo(label: String, newChild: Node) extends RewriteRule { def addChild(n: Node, newChild: Node) = n match { case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*) case _ => error("Can only add children to elements!") } override def transform(n: Node) = n match { case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild) case other => other }}
But when I try to use this code, my IDE complains that the Elem creation isn't right because the Elem extractor (i.e., the unapply that filled the case statement) has created a sequence of Node, whereas the constructor (the apply method) wants a few Strings and then a Node:
object Elem { def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = new Elem(prefix,label,attributes,scope,child:_*)
def unapplySeq(n: Node) = n match { case _: SpecialNode | _: Group => None case _ => Some((n.prefix, n.label, n.attributes, n.scope, n.child)) }}
I'm confused as to how this could ever work. Aren't the apply() and unapply() methods out-of-sync, in that you could never unapply() and turn around and feed those results into apply()?
I'm sure I'm misunderstanding something, but I'm not sure what it is. If someone could straighten me out and help me understand why the above code doesn't work and how it might be made to work, I'd GREATLY appreciate it.
Thanks,Kenner
class AddChildrenTo(label: String, newChild: Node) extends RewriteRule { def addChild(n: Node, newChild: Node) = n match { case Elem(prefix, label, attribs, scope, child @ _*) => Elem(prefix, label, attribs, scope, child ++ newChild : _*) case _ => error("Can only add children to elements!") } override def transform(n: Node) = n match { case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild) case other => other }}
But when I try to use this code, my IDE complains that the Elem creation isn't right because the Elem extractor (i.e., the unapply that filled the case statement) has created a sequence of Node, whereas the constructor (the apply method) wants a few Strings and then a Node:
object Elem { def apply(prefix: String,label: String, attributes: MetaData, scope: NamespaceBinding, child: Node*) = new Elem(prefix,label,attributes,scope,child:_*)
def unapplySeq(n: Node) = n match { case _: SpecialNode | _: Group => None case _ => Some((n.prefix, n.label, n.attributes, n.scope, n.child)) }}
I'm confused as to how this could ever work. Aren't the apply() and unapply() methods out-of-sync, in that you could never unapply() and turn around and feed those results into apply()?
I'm sure I'm misunderstanding something, but I'm not sure what it is. If someone could straighten me out and help me understand why the above code doesn't work and how it might be made to work, I'd GREATLY appreciate it.
Thanks,Kenner
Sun, 2012-01-22, 22:11
#2
Re: Mutable XML and Elem apply/unapply conflict?
On Sun, Jan 22, 2012 at 17:40, Kenner Stross wrote:
>
> But when I try to use this code, my IDE complains that the Elem creation
> isn't right because the Elem extractor (i.e., the unapply that filled the
> case statement) has created a sequence of Node, whereas the constructor (the
> apply method) wants a few Strings and then a Node:
And then a sequence of nodes, as indicated by the vargarg annotation (Node*).
>
> object Elem {
> def apply(prefix: String,label: String, attributes: MetaData, scope:
> NamespaceBinding, child: Node*) =
> new Elem(prefix,label,attributes,scope,child:_*)
>
> def unapplySeq(n: Node) = n match {
> case _: SpecialNode | _: Group => None
> case _ => Some((n.prefix, n.label,
> n.attributes, n.scope, n.child))
> }
> }
>
> I'm confused as to how this could ever work. Aren't the apply() and
> unapply() methods out-of-sync, in that you could never unapply() and turn
> around and feed those results into apply()?
>
> I'm sure I'm misunderstanding something, but I'm not sure what it is. If
> someone could straighten me out and help me understand why the above code
> doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>
> Thanks,
> Kenner
>
Mon, 2012-01-23, 16:51
#3
Re: Mutable XML and Elem apply/unapply conflict?
Sorry, I meant to say a sequence of Nodes after the strings.
I use IntelliJ IDEA 11.0.1, and have found it to be quite accurate in
its marking of problems. In this case, it has underlined "prefix,
label" each with the message: "Type mismatch, expected String, actual
Node." Next, "attribs" is underlined, with the message: "Type
mismatch, expected MetaData, actual Node." Finally, "scope" is also
underlined, and has the message: "Type mismatch, expected
NamespaceBinding, actual Node."
These messages make sense to me given that Elem.apply() is expecting a
String, String, MetaData, NamespaceBinding and Node*, and that
unapplySeq() has returned only a sequence of Nodes. I'm sure I'm
misunderstanding something (as IntelliJ is too, perhaps), as I don't
see how this apply() and unapplySeq() could ever be compatible with
each other.
Thanks for your help.
Kenner
On Jan 22, 12:59 pm, Daniel Sobral wrote:
> On Sun, Jan 22, 2012 at 17:40, Kenner Stross wrote:
>
> > But when I try to use this code, my IDE complains that the Elem creation
> > isn't right because the Elem extractor (i.e., the unapply that filled the
> > case statement) has created a sequence of Node, whereas the constructor (the
> > apply method) wants a few Strings and then a Node:
>
> And then a sequence of nodes, as indicated by the vargarg annotation (Node*).
>
>
>
>
>
>
>
>
>
>
>
> > object Elem {
> > def apply(prefix: String,label: String, attributes: MetaData, scope:
> > NamespaceBinding, child: Node*) =
> > new Elem(prefix,label,attributes,scope,child:_*)
>
> > def unapplySeq(n: Node) = n match {
> > case _: SpecialNode | _: Group => None
> > case _ => Some((n.prefix, n.label,
> > n.attributes, n.scope, n.child))
> > }
> > }
>
> > I'm confused as to how this could ever work. Aren't the apply() and
> > unapply() methods out-of-sync, in that you could never unapply() and turn
> > around and feed those results into apply()?
>
> > I'm sure I'm misunderstanding something, but I'm not sure what it is. If
> > someone could straighten me out and help me understand why the above code
> > doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>
> > Thanks,
> > Kenner
>
> --
> Daniel C. Sobral
>
> I travel to the future all the time.
Mon, 2012-01-23, 17:01
#4
Re: Mutable XML and Elem apply/unapply conflict?
But... I finally was able to run a test this morning, and the code
does appear to execute correctly. So... it is apparently just a
misunderstanding on my part (and IntelliJ's, too). So my question
remains: why is this apply() compatible with this unapply()? What
piece of this puzzle am I misunderstanding?
Thanks,
Kenner
On Jan 22, 11:40 am, Kenner Stross wrote:
> There was a discussion on StackOverflow on ways to insert a node into an
> XML structure, which is immutable by nature
> (seehttp://stackoverflow.com/questions/2199040/scala-xml-building-adding-...).
> One of the techniques proposed by Daniel Sobral looked basically like this:
>
> class AddChildrenTo(label: String, newChild: Node) extends RewriteRule {
> def addChild(n: Node, newChild: Node) = n match {
> case Elem(prefix, label, attribs, scope, child @ _*) =>
> Elem(prefix, label, attribs, scope, child ++ newChild : _*)
> case _ => error("Can only add children to elements!")
> }
> override def transform(n: Node) = n match {
> case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild)
> case other => other
> }
>
> }
>
> But when I try to use this code, my IDE complains that the Elem creation
> isn't right because the Elem extractor (i.e., the unapply that filled the
> case statement) has created a sequence of Node, whereas the constructor
> (the apply method) wants a few Strings and then a Node:
>
> object Elem {
> def apply(prefix: String,label: String, attributes: MetaData, scope:
> NamespaceBinding, child: Node*) =
> new Elem(prefix,label,attributes,scope,child:_*)
>
> def unapplySeq(n: Node) = n match {
> case _: SpecialNode | _: Group => None
> case _ => Some((n.prefix, n.label,
> n.attributes, n.scope, n.child))
> }
>
> }
>
> I'm confused as to how this could ever work. Aren't the apply() and
> unapply() methods out-of-sync, in that you could never unapply() and turn
> around and feed those results into apply()?
>
> I'm sure I'm misunderstanding something, but I'm not sure what it is. If
> someone could straighten me out and help me understand why the above code
> doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>
> Thanks,
> Kenner
Mon, 2012-01-23, 18:01
#5
Re: Re: Mutable XML and Elem apply/unapply conflict?
On Mon, Jan 23, 2012 at 13:44, Kenner Stross wrote:
> Sorry, I meant to say a sequence of Nodes after the strings.
>
> I use IntelliJ IDEA 11.0.1, and have found it to be quite accurate in
> its marking of problems. In this case, it has underlined "prefix,
> label" each with the message: "Type mismatch, expected String, actual
> Node." Next, "attribs" is underlined, with the message: "Type
> mismatch, expected MetaData, actual Node." Finally, "scope" is also
> underlined, and has the message: "Type mismatch, expected
> NamespaceBinding, actual Node."
>
> These messages make sense to me given that Elem.apply() is expecting a
> String, String, MetaData, NamespaceBinding and Node*, and that
> unapplySeq() has returned only a sequence of Nodes. I'm sure I'm
> misunderstanding something (as IntelliJ is too, perhaps), as I don't
> see how this apply() and unapplySeq() could ever be compatible with
> each other.
???
I don't understand why do you think unapplySeq is returning a sequence
of nodes. Here's the code you pasted:
object Elem {
def apply(prefix: String,label: String, attributes: MetaData, scope:
NamespaceBinding, child: Node*) =
new Elem(prefix,label,attributes,scope,child:_*)
def unapplySeq(n: Node) = n match {
case _: SpecialNode | _: Group => None
case _ => Some((n.prefix, n.label,
n.attributes, n.scope, n.child))
}
}
Specifically: Some((n.prefix, n.label, n.attributes, n.scope, n.child))
There: String, String, Metadata, NamespaceBinding and Seq[Node].
Mon, 2012-01-23, 18:11
#6
Re: Re: Mutable XML and Elem apply/unapply conflict?
On Mon, Jan 23, 2012 at 14:00, Kenner Stross wrote:
> But... I finally was able to run a test this morning, and the code
> does appear to execute correctly. So... it is apparently just a
> misunderstanding on my part (and IntelliJ's, too). So my question
> remains: why is this apply() compatible with this unapply()? What
> piece of this puzzle am I misunderstanding?
Ok... question: are you assuming unapplySeq returns a Seq[Node]
because it's unapply*Seq*?
>
> Thanks,
> Kenner
>
>
> On Jan 22, 11:40 am, Kenner Stross wrote:
>> There was a discussion on StackOverflow on ways to insert a node into an
>> XML structure, which is immutable by nature
>> (seehttp://stackoverflow.com/questions/2199040/scala-xml-building-adding-...).
>> One of the techniques proposed by Daniel Sobral looked basically like this:
>>
>> class AddChildrenTo(label: String, newChild: Node) extends RewriteRule {
>> def addChild(n: Node, newChild: Node) = n match {
>> case Elem(prefix, label, attribs, scope, child @ _*) =>
>> Elem(prefix, label, attribs, scope, child ++ newChild : _*)
>> case _ => error("Can only add children to elements!")
>> }
>> override def transform(n: Node) = n match {
>> case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild)
>> case other => other
>> }
>>
>> }
>>
>> But when I try to use this code, my IDE complains that the Elem creation
>> isn't right because the Elem extractor (i.e., the unapply that filled the
>> case statement) has created a sequence of Node, whereas the constructor
>> (the apply method) wants a few Strings and then a Node:
>>
>> object Elem {
>> def apply(prefix: String,label: String, attributes: MetaData, scope:
>> NamespaceBinding, child: Node*) =
>> new Elem(prefix,label,attributes,scope,child:_*)
>>
>> def unapplySeq(n: Node) = n match {
>> case _: SpecialNode | _: Group => None
>> case _ => Some((n.prefix, n.label,
>> n.attributes, n.scope, n.child))
>> }
>>
>> }
>>
>> I'm confused as to how this could ever work. Aren't the apply() and
>> unapply() methods out-of-sync, in that you could never unapply() and turn
>> around and feed those results into apply()?
>>
>> I'm sure I'm misunderstanding something, but I'm not sure what it is. If
>> someone could straighten me out and help me understand why the above code
>> doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>>
>> Thanks,
>> Kenner
Mon, 2012-01-23, 18:31
#7
Re: Mutable XML and Elem apply/unapply conflict?
Oops... how very embarrassing... In my haste, my newness to Scala, and
my assumption that something was wrong per my IDE, I did confuse
unapplySeq()'s input params with its return values. Yes, you are
absolutely right, apply() and unapplySeq() are perfectly in sync. Of
course.
I guess I've stumbled across a small mistake on the part of IntelliJ,
in marking those values as incorrect.
Thanks for setting me straight on this. Sorry to have wasted your time
with my mistake.
Thanks,
Kenner
On Jan 23, 8:57 am, Daniel Sobral wrote:
> On Mon, Jan 23, 2012 at 14:00, Kenner Stross wrote:
> > But... I finally was able to run a test this morning, and the code
> > does appear to execute correctly. So... it is apparently just a
> > misunderstanding on my part (and IntelliJ's, too). So my question
> > remains: why is this apply() compatible with this unapply()? What
> > piece of this puzzle am I misunderstanding?
>
> Ok... question: are you assuming unapplySeq returns a Seq[Node]
> because it's unapply*Seq*?
>
>
>
>
>
>
>
>
>
>
>
> > Thanks,
> > Kenner
>
> > On Jan 22, 11:40 am, Kenner Stross wrote:
> >> There was a discussion on StackOverflow on ways to insert a node into an
> >> XML structure, which is immutable by nature
> >> (seehttp://stackoverflow.com/questions/2199040/scala-xml-building-adding-...).
> >> One of the techniques proposed by Daniel Sobral looked basically like this:
>
> >> class AddChildrenTo(label: String, newChild: Node) extends RewriteRule {
> >> def addChild(n: Node, newChild: Node) = n match {
> >> case Elem(prefix, label, attribs, scope, child @ _*) =>
> >> Elem(prefix, label, attribs, scope, child ++ newChild : _*)
> >> case _ => error("Can only add children to elements!")
> >> }
> >> override def transform(n: Node) = n match {
> >> case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild)
> >> case other => other
> >> }
>
> >> }
>
> >> But when I try to use this code, my IDE complains that the Elem creation
> >> isn't right because the Elem extractor (i.e., the unapply that filled the
> >> case statement) has created a sequence of Node, whereas the constructor
> >> (the apply method) wants a few Strings and then a Node:
>
> >> object Elem {
> >> def apply(prefix: String,label: String, attributes: MetaData, scope:
> >> NamespaceBinding, child: Node*) =
> >> new Elem(prefix,label,attributes,scope,child:_*)
>
> >> def unapplySeq(n: Node) = n match {
> >> case _: SpecialNode | _: Group => None
> >> case _ => Some((n.prefix, n.label,
> >> n.attributes, n.scope, n.child))
> >> }
>
> >> }
>
> >> I'm confused as to how this could ever work. Aren't the apply() and
> >> unapply() methods out-of-sync, in that you could never unapply() and turn
> >> around and feed those results into apply()?
>
> >> I'm sure I'm misunderstanding something, but I'm not sure what it is. If
> >> someone could straighten me out and help me understand why the above code
> >> doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>
> >> Thanks,
> >> Kenner
>
> --
> Daniel C. Sobral
>
> I travel to the future all the time.
What IDE? I just verified that the code is well typed as written.
On Sun, Jan 22, 2012 at 17:40, Kenner Stross wrote:
> There was a discussion on StackOverflow on ways to insert a node into an XML
> structure, which is immutable by nature
> (see http://stackoverflow.com/questions/2199040/scala-xml-building-adding-children-to-existing-nodes).
> One of the techniques proposed by Daniel Sobral looked basically like this:
>
>
> class AddChildrenTo(label: String, newChild: Node) extends RewriteRule {
> def addChild(n: Node, newChild: Node) = n match {
> case Elem(prefix, label, attribs, scope, child @ _*) =>
> Elem(prefix, label, attribs, scope, child ++ newChild : _*)
> case _ => error("Can only add children to elements!")
> }
> override def transform(n: Node) = n match {
> case n @ Elem(_, `label`, _, _, _*) => addChild(n, newChild)
> case other => other
> }
> }
>
> But when I try to use this code, my IDE complains that the Elem creation
> isn't right because the Elem extractor (i.e., the unapply that filled the
> case statement) has created a sequence of Node, whereas the constructor (the
> apply method) wants a few Strings and then a Node:
>
> object Elem {
> def apply(prefix: String,label: String, attributes: MetaData, scope:
> NamespaceBinding, child: Node*) =
> new Elem(prefix,label,attributes,scope,child:_*)
>
> def unapplySeq(n: Node) = n match {
> case _: SpecialNode | _: Group => None
> case _ => Some((n.prefix, n.label,
> n.attributes, n.scope, n.child))
> }
> }
>
> I'm confused as to how this could ever work. Aren't the apply() and
> unapply() methods out-of-sync, in that you could never unapply() and turn
> around and feed those results into apply()?
>
> I'm sure I'm misunderstanding something, but I'm not sure what it is. If
> someone could straighten me out and help me understand why the above code
> doesn't work and how it might be made to work, I'd GREATLY appreciate it.
>
> Thanks,
> Kenner
>