2011-01-13 45 views
5

我想在Scala XML Elem对象和另一个XML元素表示之间隐式转换,在我的情况下是dom4j Element。我写了下面的隐式转换:Scala集合类型之间的隐式转换

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

到目前为止这么好,这工作。

现在我还需要所述元素的集合来转换两种方式。首先,我是否绝对需要编写额外的转换方法?如果我不这样做,事情似乎并不奏效。

我试着写:

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

这看上去并不是很理想,因为如果转换方法接受一个Traversable,那么它也将返回一个Traversable。如果我通过一个List,我也会得到一个Traversable。所以我假设转换应该以某种方式参数化。

那么写这些转换的标准方式是为了尽可能通用?

回答

1

我认为这可能是牵扯太远了。尤其是当你可以只使用转换器的方法在地图

val listOfElements = listOfElems map elemToElement(_) 

我想你会的水平简洁越来越为模糊。我会创建一个转换器层,并只在其中一个表示中工作,以防止事情变得混乱。

+0

为什么从`X`自动转换为`Y`而不是从`List [X]`到List [Y]`自动转换?它充满了完全相同的需求,即您实际上并不关心使用哪种表示形式,并且希望编译器为您处理繁忙工作。 – 2011-01-13 15:49:11

+0

这主要是风格和最佳实践的问题。要求暗示工作,那么多魔术就是在寻求麻烦。在我看来,它们是斯卡拉的BFG之一:小心你指向它的地方。 – sblundy 2011-01-13 16:09:00

2

这是不平凡的,所以为了得到你想要的东西,我想你必须深入一点。这篇文章解释了很多关于scala集合是如何工作的(并且有趣的是它也是这样):http://www.artima.com/scalazine/articles/scala_collections_architecture.html

你基本上和List.map(...)(或者TraversableLike一样)和类似的方法....只有在隐式转换之外。

更新:

我开始试验这种一点点写基于什么TraversableLike.map(...)做了转换。但是,我发现,即使没有它,它也能奏效。似乎Scala支持开箱即用(至少在我的机器上:-)):

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

这就是你以后的样子?