开发者

Implicit conversion between Scala collection types

I would like to implicitly convert between the Scala XML Elem object and another representation of an XML element, in my case dom4j Element. I wrote the following implicit conversions:

implicit def elemToElement(e: Elem): Element = ... do conversion here ...
implicit def elementToElem(e: Element): Elem = ... do conversion here ...

So far so good, this works.

Now I also need collections of said elements to convert both ways. First, do I absolutely need to write additional conversion methods? Things didn't seem to work if I didn't.

I tried to write the following:

implicit def elemTToElementT(t: Traversable[Elem]) = t map (elemToElement(_))
implicit 开发者_JAVA百科def elementTToElemT(t: Traversable[Element]) = t map (elementToElem(_))

This doesn't look too ideal because if the conversion method takes a Traversable, then it also returns a Traversable. If I pass a List, I also get a Traversable out. So I assume the conversion should be parametrized somehow.

So what's the standard way of writing these conversions in order to be as generic as possible?


This is non-trivial so in order get what you want I think you'll have to go a bit deeper. This article explains a lot about how the scala collections work (and interesting read it is too): http://www.artima.com/scalazine/articles/scala_collections_architecture.html

You're basically trying to do the same as List.map(...) (or TraversableLike which has the implementation) and similar methods.... only with implicit conversion in addition.

Update:

I started experimenting a little bit with this and wrote a conversion based on what TraversableLike.map(...) does. However I discovered that it worked even without it. Seems like Scala supports it out of the box (at least on my machine :-) ):

case class Element(e: Elem)
implicit def elemToElement(e: Elem): Element = Element(e)
implicit def elementToElem(e: Element): Elem = e.e

val a: List[Element] = List(<a/>, <b/>, <c/>)
val b: List[Elem] = List(Element(<a/>), Element(<b/>), Element(<c/>))
val c: Set[Element] = Set(<a/>, <b/>, <c/>)

This was what you were after?


I think this might be taking implicits too far. Especially as you can just use the converter method in a map

val listOfElements = listOfElems map elemToElement(_)

I think that the level conciseness you're going for is getting into obfuscation. I would create a converter layer and work in only one of the representations so as to keep things from getting to confused.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜