开发者

Why is scala.xml.Atom type-parameterized?

开发者 https://www.devze.com 2023-02-14 10:35 出处:网络
I noticed that scala.xml.Atom takes a type parameter A, even though all of its subclasses extend Atom[String], and the documentation says \"The class Atom provides an XML node for text (PCDATA).\"

I noticed that scala.xml.Atom takes a type parameter A, even though all of its subclasses extend Atom[String], and the documentation says "The class Atom provides an XML node for text (PCDATA)."

Are there legitimate use cases for instantiating an Atom with a type parameter other than string?

More concretely, I'm interested in using Scala XML literal to defin开发者_运维问答e sort of a nice DSL for defining an in-memory tree-based document structure, where many of the nodes would be existing scala classes. It would be super nice to use <document>{new JButton("Hi")}</document> and access the non-text data in the Atom[JButton] without having to define an XML serialization scheme for every existing class.

Is that a legitimate use case, or am I abusing the current implementation of Scala's XML library?


if you take a look into the sources the reason is revealled. Atom is generic because it converts the passed object to a String. So you can pass a JButton to it but then it will just call its toString method. (line 48 is what matters)

I guess it is possible to get the data back out of the atom:

val doc = <document>{ 42 }</document>

doc.child.head match { 
  case i: Atom[Int] => i.data / 7 
  case _ => error("Unsupported type")
}

returns 6. So your plan would work. I still think a tree based on abstract classes and case classes would be a better choice because with your method all type safety is gone as you can pass in everything, so that type errors will not be discovered until runtime.


If you look at http://sites.google.com/site/burakemir/scalaxbook.docbk.html?attredirects=0, you will find that Atom was indeed intended "for nodes containing data of any type, e.g. int, Date".

As you observed, embedded expressions inside elements are turned into atoms if they aren't strings, for example

<foo>{42}</foo>

has as child an Atom[Int].

To add an atom into an attribute value, you have to write

<foo life={new Atom(42)}>

(In the "book", it was just Atom(42), but that was then--Atom is no longer a case class since case class inheritance has been deprecated.)

So, yes, what you want to do is perfectly within the spirit of the design.

But the design is several years old, and a good number of people are unhappy about some of the decisions. The XML support in Scala might be cleaned up in the future, and this rather obscure feature might not survive.

0

精彩评论

暂无评论...
验证码 换一张
取 消