2010-10-28 8 views
6

Estoy tratando de integrar una aplicación Lift en algún código Java existente. En uno de mis fragmentos, tengo una matriz de objetos Java que necesito asignar a un NodeSeq. Puedo obtener un Array of Node, pero no un NodeSeq. (Al menos, no de manera muy funcional).¿Cómo convierto Array [Node] a NodeSeq?

import scala.xml.NodeSeq 

// pretend this is code I can't do anything about 
val data = Array("one", "two", "three") 

// this is the function I need to write 
def foo: NodeSeq = data.map { s => <x>{s}</x> } 
//      ^
// error: type mismatch; 
// found : Array[scala.xml.Elem] 
// required: scala.xml.NodeSeq 

¿Cuál es la forma más limpia de hacer esto?

+1

Siempre tiene el método '++' disponible :-) 'new NodeSeq() ++ theArray_Elm_thing'. Puede haber mejores maneras. Feliz codificación. –

+1

NodeSeq es abstracto, por lo que 'new NodeSeq()' no funciona. –

Respuesta

8

yo simplemente convertir map de salida con la secuencia (dado que Seq[Node] es un super-clase de NodeSeq)

scala> def foo: NodeSeq = data.map { s => <x>{s}</x> } toSeq 
foo: scala.xml.NodeSeq 

o utilizar foldLeft en lugar de map

scala> def foo: NodeSeq = (Seq[Node]() /: data) {(seq, node)=> seq ++ <x>{node}</x>} 
foo: scala.xml.NodeSeq 
+1

toSeq es la elegancia que estoy buscando. ¡Gracias! – leedm777

+0

Usando el mapa y luego aSeq significa que está creando 2 colecciones. Usando BreakOut está creando 1. – IttayD

+2

'toSeq' crea un contenedor (http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html), por lo que hay una pena de rendimiento miserable. http://www.scala-lang.org/docu/files/collections-api/collections_38.html –

9
scala> import collection.breakOut 
import collection.breakOut 

scala> def foo: NodeSeq = data.map { s => <x>{s}</x> }(breakOut) 
foo: scala.xml.NodeSeq 

El mapa de métodos en realidad tiene dos listas de argumentos. El primero acepta una función, que pasaste. El segundo acepta un objeto CanBuildFrom que se usa para crear un constructor que luego construye la secuencia de retorno. Este argumento es implícito, por lo que generalmente el compilador lo llena por usted. Acepta 3 parámetros de tipo: De, T, A. Hay varios implícitos predefinidos (incluido en el objeto NodeSeq), pero ninguno de ellos coincide con From = Array, T = Node, To = NodeSeq.

breakOut resuelve esto: es un método genérico que devuelve una instancia CanBuildFrom al buscar un CanBuildFrom implícito [Nothing, T, To]. De acuerdo con las reglas de búsqueda implícita, cualquier CanBuildFrom que coincida con T, To y tiene desde> Nada es aceptable. En este caso: canBuildFrom en Array objeto

+2

Me pareció apropiado enlazar con la pregunta breakOut: http://stackoverflow.com/questions/1715681/scala-2-8-breakout –

1

Está buscando este método en el objeto complementario NodeSeq.

NodeSeq.fromSeq(s: Seq[Node]) 
Cuestiones relacionadas