How to write two dimensional array in xml in Scala 2.8.0
The following code (copied from the question about a year ago ) works fine under Scala 2.7.7, but does not behave correctly under Scala 2.8.0 (Beta 1, RC8).
import scala.xml
class Person(name : String, age : Int) {
def toXml(): xml.Elem =
<person><name>{ name }</name><age>{ age }</age></person>
}
def peopleToXml(people: Array[Person]): xml.Elem = {
<people>{ for {person <- people} yield person.toXml }</people>
}
val data = Array(new Person("joe",40), new Person("mary", 35))
println(peopleToXml(data))
The output (according to 2.7.7) should be:
<people><person><name>joe</name><age>40</age></person><person><name>mary</name><age>35</age></person></people>
but instead it is issued as:
<people>\[Lscala.xml.Elem;@17821782</people>
How can I get myself to behave like in 2.7.x?
a source to share
This code requires two conversions. First, you need to convert Array[xml.Elem]
which is returned to understand for Seq[xml.Elem]
, and then the implicit conversion to xml.NodeSeq
converts that code to xml.NodeSeq
.
If you change peopleToXml
to the following, it works as expected:
def peopleToXml(people: Array[Person]): xml.Elem = {
val a: Seq[xml.Elem] = for {person <- people} yield person.toXml
<people>{a}</people>
}
You can also do the following if you like it :-)
def peopleToXml(people: Array[Person]): xml.Elem = {
<people>{(for {person <- people} yield person.toXml): Seq[xml.Elem]}</people>
}
a source to share
As pst says, the result is what you would expect from a real Java array. One of the changes between 2.7 and 2.8 is that Array[T]
it is now a real Java array. The new collection design means that performing Scala collection operations on a Java array (like map
in your example) will return a Java array as the result. This means that the following
for {person <- people} yield person.toXml
Used to not return a Java array, but now does. You can fix the problem by changing the type of people
your method argument peopleToXml
as follows:
def peopleToXml(people: Seq[Person]): xml.Elem = {
<people>{ for {person <- people} yield person.toXml }</people>
}
This will mean that when you call this method with an argument Array
, the array will be implicitly converted to WrappedArray
, which behaves as you expect. This will also give you the ability to call this method with non-array-specific arrays.
a source to share
The output returns a real Java array, which is a string according to normal Java rules. This is given by the output "[Ltype; @ref".
Perhaps you can convert it (people or result) to a list and improve the "semantics". I believe Scala 2.7.7 fully returns the collection type (not an array).
Fighting bit-rota with types talks about the new Scala 2.8 Setting up collections "in general" but not specifics. There might be more kindness on scala -lang.org and as always, welcome to visit # scala on freenode :-)