以下代码(从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中那样?
答案 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: - )