2010-10-28 2 views
6

Я пытаюсь интегрировать приложение Lift в какой-то существующий Java-код. В одном из моих фрагментов у меня есть массив объектов Java, которые мне нужно отобразить в NodeSeq. Я могу получить Array of Node, но не NodeSeq. (По крайней мере, не очень функционально-выглядящий).Как преобразовать Array [Node] в 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 

Какой самый чистый способ сделать это?

+1

У вас всегда есть метод '++' :-) 'new NodeSeq() ++ theArray_Elm_thing'. Могут быть лучшие способы. Счастливое кодирование. – 2010-10-28 21:00:33

+1

NodeSeq является абстрактным, поэтому «новый NodeSeq() не работает. –

ответ

8

Я бы просто преобразовать map вывод в последовательности (при условии, что Seq[Node] супер-класс NodeSeq)

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

или использовать foldLeft вместо map

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

toSeq - это элегантность, которую я ищу. Благодаря! – leedm777

+0

Использование карты, а затем toSeq означает, что вы создаете 2 коллекции. Использование breakOut, которое вы создаете 1. – IttayD

+2

'toSeq' создает оболочку (http://www.scala-lang.org/api/current/scala/collection/mutable/WrappedArray.html), поэтому есть жалкое снижение производительности. 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 

На карте метода фактически есть два списка аргументов. Первая принимает функцию, которую вы передали. Второй принимает объект CanBuildFrom, который используется для создания построителя, который затем создает возвращаемую последовательность. Этот аргумент неявный, поэтому обычно компилятор заполняет его для вас. Он принимает 3 типа параметров: From, T, To. Существует несколько предиффайтов (в том числе в объекте NodeSeq), но ни один из них не соответствует From = Array, T = Node, To = NodeSeq.

breakOut решает это: это общий метод, который возвращает экземпляр CanBuildFrom путем поиска неявного CanBuildFrom [Nothing, T, To]. В соответствии с неявными правилами поиска любой CanBuildFrom, который соответствует T, To и имеет From> Nothing, является приемлемым. В этом случае: canBuildFrom в массив объектов

+2

Кажется уместным ссылаться на breakOut вопрос: http://stackoverflow.com/questions/1715681/scala-2-8-breakout –

1

Вы ищете этот метод для сопутствующего объекта NodeSeq.

NodeSeq.fromSeq(s: Seq[Node]) 
Смежные вопросы