2017-05-16 31 views
0

我寫了一個簡單的隱式函數:mkString()的一個版本工作原理相同,但如果在連接的任何參數中都找到分隔符,則會引發錯誤。我想,使其工作在所有序列狀的東西,所以我聲明,如下所示:Scala 2.10在TraversableOnce上的隱式函數應該接受一個數組,但不會

object SafeMkString { 
    implicit class SafeMkStringHelper[T](values: TraversableOnce[T]) { 
    def safeMkString(sep: String) = { 
     values.map { v => 
     val asStr = v.toString 
     if (asStr.contains(sep)) 
      throw new IllegalArgumentException("Value %s in %s contains separator %s" format 
      (asStr, values, sep)) 
     else 
      asStr 
     }.mkString(sep) 
    } 
    } 
} 

這工作對大多數的對象,但在斯卡拉2.10 Array[String]類型的東西失敗。這是因爲Scala中的數組只是Java數組的別名,並不會從TraversableOnce繼承。但是,存在從ArrayWrappedArray的隱式轉換,即確實從TraversableOnce繼承。 Scala中有一些規則不允許從A→B然後從B→C進行隱式轉換?除了手動創建另一個隱式類,明確應用safeMkStringArray[T]以外,有什麼方法可以實現此工作嗎?

回答

3

在回答你的第一個問題,這是從Programming in Scala (1st Edition),第21章:

一在一次一個規則:只有一個隱含的嘗試。編譯器將永遠不會將x + y重寫爲convert1(convert2(x))+ y。這樣做會導致編譯時間在錯誤代碼上顯着增加,並且會增加程序員編寫的內容與程序實際執行的內容之間的差異。爲了理智,當編譯器已經在嘗試另一個隱式轉換時,編譯器不會插入更多的隱式轉換。然而,通過隱含隱含參數可以規避這種限制,本章後面將對此進行介紹。

+0

Doh,這確實是RTFM的一個例子。 –

2

由@jwvh答案(尤其是在引文的最後一行)的啓發,我想出了以下內容:

implicit class CanBeTraversable[A, T](a: A)(implicit ev: A => TraversableOnce[T]){ 
    def safeMkString(sep: String) = { 
    val values = ev(a) 
    ... //put here the body of your method 
} 

它的作用是給來自一個具有任何類型A的隱式轉換對於某些T,隱式轉換爲TraversableOnce[T]。這適用於List,因爲=:= : List[T] => List[T]是一個隱式轉換(另外,因爲Function1在其第二個參數Function1[List[T], List[T]] <: Function1[List[T], TraversableOnce[T]]中是協變的)。它也適用於Array,因爲它隱式轉換爲WrappedArray

相關問題