#scala #anti-xml
#скала #анти-XML #scala
Вопрос:
Я перепостирую это от scala-user:
У меня есть следующее:
object XmlTest {
import com.codecommit.antixml._
implicit def toPicker(nodes: Group[Node]): Picker = new Picker(nodes)
class Picker(nodes: Group[Node]) {
def pick[A <: Node : ClassManifest]: Group[A] = nodes collect {
case a if implicitly[ClassManifest[A]].erasure.isInstance(a) => a.asInstanceOf[A]
}
}
def testCollect(elems: Group[Elem]) {
println("size before collect = " elems.size)
val es = elems collect {
case e if e.name == "c" => println("element name is " e.name); e
}
println("size after collect = " es.size)
}
def main(args: Array[String]) {
val xml = XML.fromString("<a><b/><c/><d/></a>")
// this works because <a> has only elements as children
testCollect(xml.children.asInstanceOf[Group[Elem]])
// pick filters collection by type
testCollect(xml.children.pick[Elem])
}
}
Когда я запустил ее, она напечатала следующее:
[info] size before collect = 3 // size is 3
[info] element name is c // element c matches
[info] size after collect = 1 // this is correct
[info] size before collect = 3 // size is the same as the previous case
[info] element name is c // element "c" is matched as well
[info] size after collect = 0 // this should be 1
Я здесь в растерянности. Что происходит?
Комментарии:
1. Маленькая деталь: вы можете написать
classManifest[A]
вместоimplicitly[ClassManifest[A]]
.2. Вы должны были четко указать, что используете анти-xml.
Ответ №1:
Похоже, это ошибка в анти-XML. Это довольно легко воспроизвести даже без всей ClassManifest
магии:
val xml = <a><b/><c/><d/></a>.anti
xml.children collect { case e => e } collect { case e => e } // => Group()
Проблема проистекает из реализации flatMap
в Zipper
. Что-то определенно не так, и неудивительно, учитывая, насколько нетривиальна реализация. Я добавлю тестовый пример и, надеюсь, исправлю его сегодня вечером.