Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert Array[Node] to NodeSeq?

I'm trying to integrate a Lift application into some existing Java code. In one of my snippets, I have an Array of Java objects that I need to map that into a NodeSeq. I can get an Array of Node's, but not a NodeSeq. (At least, not in very functional-looking way).

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

What's the cleanest way to do this?

like image 346
leedm777 Avatar asked Oct 28 '10 20:10

leedm777


3 Answers

scala> import collection.breakOut
import collection.breakOut

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

The method map actually has two argument lists. The first accepts a function, which you passed. The second accepts a CanBuildFrom object which is used to create a builder that then builds the returning sequence. This argument is implicit, so usually the compiler fills it for you. It accepts 3 type parameters: From, T, To. There are several predef implicits (including in object NodeSeq), but none of them matches From=Array, T=Node, To=NodeSeq.

breakOut solves this: it is a generic method that returns a CanBuildFrom instance by searching for an implicit CanBuildFrom[Nothing, T, To]. According to the implicit search rules, any CanBuildFrom that matches T, To and has From > Nothing is acceptable. In this case: canBuildFrom in object Array

like image 113
IttayD Avatar answered Oct 19 '22 14:10

IttayD


I would simply convert map output to sequence (given that Seq[Node] is a super-class of NodeSeq)

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

or use foldLeft instead of map

scala> def foo: NodeSeq = (Seq[Node]() /: data) {(seq, node)=> seq ++ <x>{node}</x>}
foo: scala.xml.NodeSeq
like image 44
Vasil Remeniuk Avatar answered Oct 19 '22 15:10

Vasil Remeniuk


You are looking for this method on the NodeSeq companion object.

NodeSeq.fromSeq(s: Seq[Node])
like image 29
Mike Beckerle Avatar answered Oct 19 '22 15:10

Mike Beckerle