2011-01-13 44 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/>) 

這就是你以後的樣子?