2011-01-13 12 views
5

Me gustaría convertir implícitamente entre el objeto Scala XML Elem y otra representación de un elemento XML, en mi caso dom4j Element. Escribí las siguientes conversiones implícitas:Conversión implícita entre los tipos de colección de Scala

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

Hasta aquí todo bien, esto funciona.

Ahora también necesito colecciones de dichos elementos para convertir en ambos sentidos. Primero, ¿necesito escribir métodos de conversión adicionales? Las cosas no parecían funcionar si no lo hacía.

Traté de escribir lo siguiente:

implicit def elemTToElementT(t: Traversable[Elem]) = t map (elemToElement(_)) 
implicit def elementTToElemT(t: Traversable[Element]) = t map (elementToElem(_)) 

Esto no se ve tan ideal, porque si el método de conversión tiene una de Traversable, entonces también devuelve una de Traversable. Si paso una Lista, también obtengo una Traversable. Así que supongo que la conversión debe ser parametrizada de alguna manera.

¿Cuál es la forma estándar de escribir estas conversiones para ser lo más genérico posible?

Respuesta

1

Creo que esto podría estar llevando implícitas demasiado lejos. Especialmente en lo que sólo se puede utilizar el método del convertidor en un mapa

val listOfElements = listOfElems map elemToElement(_) 

creo que el nivel de la concisión que vamos a dar es entrar en la ofuscación. Crearía una capa convertidora y trabajaría en una sola de las representaciones para evitar que las cosas se confundan.

+0

¿Por qué es más confuso poder convertir automáticamente de 'X' a' Y' que de 'List [X]' to 'List [Y]'? Satisface exactamente la misma necesidad, es decir, que realmente no le importa qué representación se utiliza y desea que el compilador maneje el trabajo ocupado por usted. –

+0

Es en gran parte una cuestión de estilo y mejores prácticas. Pedir implicidades para que funcione tanta magia es pedir problemas. Son, en mi opinión, uno de los BFG de scala: tenga cuidado con lo que apunta. – sblundy

+0

Estoy de acuerdo con Rex: no estoy de acuerdo con que sea confuso. Por el contrario, yo hubiera esperado incluso que la definición de una conversión implícita de un tipo determinado automáticamente hiciera que la conversión implícita de (digamos "monádica") contenedores para ese tipo también funcionara. – ebruchez

2

Esto no es trivial, así que para obtener lo que quieres creo que tendrás que profundizar un poco. Este artículo explica mucho sobre cómo funcionan las colecciones scala (y también es interesante leerlo): http://www.artima.com/scalazine/articles/scala_collections_architecture.html

Básicamente intenta hacer lo mismo que List.map (...) (o TraversableLike que tiene la implementación) y métodos similares ... solo con conversión implícita además.

Actualización:

empecé a experimentar un poco con esto y escribí una conversión basado en lo que hace TraversableLike.map (...). Sin embargo, descubrí que funcionaba incluso sin él. Parece que lo apoya Scala fuera de la caja (al menos en mi máquina :-)):

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/>) 

Esto fue lo que buscabas?

+0

Gracias por el puntero en realidad revisé ese documento hace un tiempo, pero esperaba una respuesta directa a mi pregunta. #laziness – ebruchez

+0

¡Guau, tu ejemplo sí funciona en REPL!Ahora la pregunta es por qué no funcionó en el contexto de mi propio código. Sospecho que es porque estoy pasando una Lista de Escala [Elem] a un método que requiere java.util.List [Elemento]. La "Regla de uno a la vez" se activa, solo se intenta una conversión implícita. Mirando más adentro. – ebruchez

+0

Mmh, por lo que no funciona al llamar funciones: 'def fa (p: List [Element]) {}; fa (b) '> error: no coincide – ebruchez

Cuestiones relacionadas