2012-05-02 23 views
0

斯卡拉很酷。但也有時由於許多看似隨意的限制以及不像我預期的那樣工作而令人非常沮喪。斯卡拉中的多個獨立含義

在這種情況下,我在Scala中編寫了一個參數解析庫。它有這個功能:

def option[T](
    name1: String, name2: String = null, name3: String = null, 
    name4: String = null, name5: String = null, name6: String = null, 
    name7: String = null, name8: String = null, name9: String = null, 
    default: T = null.asInstanceOf[T], 
    metavar: String = null, 
    choices: Seq[T] = null, 
    aliases: Map[T, Iterable[T]] = null, 
    help: String = "") 
(implicit convert: (String, String, ArgParser) => T, m: Manifest[T]) = { 
    optionSeq[T](nonNullVals(name1, name2, name3, name4, name5, name6, 
    name7, name8, name9), 
    metavar = metavar, default = default, choices = choices, 
    aliases = aliases, help = help)(convert, m) 
} 

本質上,這聲明瞭一個給定類型的普通選項參數。有一個隱含的函數,它被一個適合於類型的默認轉換器填充。還有一個隱含的清單,這是必要的,因爲我需要能夠在某些情況下對其進行處理。

這工作,直到我試圖實際提供一個非默認轉換器。正如所寫的,你不能只提供轉換器,但也不得不提供一個清單,我不知道該怎麼辦,反正它是可怕的醜 - 清單是一個討厭的雜物, JVM中的碎片,並且不應該暴露給最終用戶。

我已經知道,Scala沒有讓你在一個單一的參數列表混用隱式和非隱含參數 - IMO任意和不必要的限制,但就這樣吧。所以我嘗試將隱式參數列表分成兩個單獨的參數列表,每個列表都有一個隱式參數列表。沒有運氣 - 斯卡拉似乎也阻止你有不止一個隱含的參數列表(另一個似乎任意的限制)。

我沒有任何想法如何解決這個問題。建議?

此外,是否有任何電流試圖解決一些對implicits這些限制在將來的斯卡拉版本(和/或拿出身邊類型擦除破碎比體現,這IMO是對接醜的工作更隱形的方式)?

回答

3

這是一個非常尷尬的方法。九個明確的名稱參數?轉換函數的隱式選擇?我不確定體現是這裏最糟糕的問題。

無論如何,你可以

class Converter[T: Manifest](val f: (String, String, ArgParser) => T) { 
    def m = manifest[T] 
} 
implicit def function_to_converter[T: Manifest](f: (String, String, ArgParser) => T) = 
    new Converter { def apply(s1: String, s2: String, ap: ArgParser) = f(s1,s2,ap) } 
} 

,然後用這個來代替這兩個參數你已經有了。這樣定義

implicit val convert_to_int: Converter = (s1: String, s2: String, ap: ArgParser) => ... 

,然後,如果用戶需要填寫明確之一,他們可以提供的功能,並把它隱式轉換所有的默認轉換器。

+0

謝謝,我會嘗試。它看起來很尷尬,因爲我試圖解決Scala非功能問題。我希望你能夠聲明一個或多個名字,加上一些命名參數,如下所示:'option [Int](「ngram」,「n-gram」,default = 3,help =「」「something」「」 )'。 –

3

您可以始終在implicitly[T]的上下文中獲得類型爲Timplicit。因此,如果您需要明確編寫編譯器將提供的隱式Manifest[T],則可以使用implicitly[Manifest[T]]來完成此操作。

只要你想在一個隱式參數列表中提供一個參數,並保持其他參數不變,就可以隱式地使用[TheTypeOfTheImplicit]來替換你不想改變的參數。

對於艙單,Predef恰好有一個捷徑,這僅僅是manifest[T](這只是implicitly[Manifest[T]]

注:implicitly不是魔術,它只是def implicitly[T](implicit e: T) = e,在Predef.

+0

謝謝。我想避免讓用戶明確地填寫清單,因爲它實際上是一個實現功能;這就是我接受其他答案的原因。 –