如何在Scala 2.8.0中将二维数组写入xml

时间:2010-04-22 05:33:27

标签: xml scala arrays

以下代码(从a question from about a year ago复制)在Scala 2.7.7下运行正常,但在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))

输出(根据2.7.7)应为:

<people><person><name>joe</name><age>40</age></person><person><name>mary</name><age>35</age></person></people>

但改为:

<people>\[Lscala.xml.Elem;@17821782</people>

如何使其表现得像在2.7.x中那样?

3 个答案:

答案 0 :(得分:4)

正如pst所说,输出是你对真正的Java数组所期望的。 2.7和2.8之间的变化之一是Array[T]现在完全是一个真正的Java数组。新的集合设计意味着在Java数组(例如示例中的map)上执行Scala集合操作将返回Java数组作为结果。这意味着以下

for {person <- people} yield person.toXml

用于不返回Java数组,但现在可以。您可以通过更改people方法的peopleToXml参数的类型来解决问题,如下所示:

def peopleToXml(people: Seq[Person]): xml.Elem = {
    <people>{ for {person <- people} yield person.toXml }</people>
}

这意味着当您使用Array参数调用此方法时,该数组将隐式转换为行为符合您预期的WrappedArray。这也可以让您使用非数组集合调用此方法。

答案 1 :(得分:3)

此代码需要两次转换。首先,您必须将for for comprehension返回的Array[xml.Elem]转换为Seq[xml.Elem],然后xml.NodeSeq中的隐式转换会将此转换为xml.NodeSeq

如果您将peopleToXml更改为以下内容,它将按预期运行:

def peopleToXml(people: Array[Person]): xml.Elem = {
  val a: Seq[xml.Elem] = for {person <- people} yield person.toXml
  <people>{a}</people>
}

如果您喜欢它,您还可以执行以下操作: - )

def peopleToXml(people: Array[Person]): xml.Elem = {
  <people>{(for {person <- people} yield person.toXml): Seq[xml.Elem]}</people>
}

答案 2 :(得分:1)

yield正在返回一个真正的java数组,它按照普通的Java规则进行字符串化。这是由“[Ltype; @ref”输出。

给出的

也许您可以将它(人员或结果)转换为List并获得更好的“字符串”语义。我想Scala 2.7.7完全返回一个不同的(非数组)集合类型。

Fighting Bit Rot With Types谈论新的Scala 2.8 Collections设置“一般”但没有详细说明。 scala-lang.org可能会有更多的好处,并且一如既往地欢迎访问freenode上的#scala: - )