2010-05-20 55 views
1

在Scala中2.8.0 RC 2這樣的定義:斯卡拉2.8:匿名函數類型推斷爲默認參數

def buttonGroup[T](values: Array[T], textProvider: T => String = (t: T => t.toString)) = ... 

提供錯誤消息:

未找到:值t

def buttonGroup[T](values: Array[T], textProvider: T => String = (_.toString)) = ... 

缺少的參數類型擴展功能{}

只有這樣的作品((X $ 1)=> X $ 1 {}的toString {}):

textProvider: T => String = (_:T).toString 

爲什麼?

回答

4

無論這些工作,沒有類型標註:

def buttonGroup[T](values: Array[T], textProvider: T => String = (t: T) => t.toString) = 0 

def buttonGroup[T](values: Array[T], textProvider: T => String = {t: T => t.toString}) = 0 

但爲什麼不是你的變化工作?

第一個實際上是無效的Scala在任何上下文中:

scala> (t: Any => t.toString) 
<console>:1: error: ';' expected but ')' found. 
     (t: Any => t.toString)) 
          ^

第二個表達式_.toString使用佔位符語法匿名的功能,並且如果所述表達具有期望的類型只適用。

scala> def foo[T] = { (_.toString) : (T => String) } 
foo: [T](T) => String 

問題是,類型取決於類型參數的參數的默認表達式沒有預期的類型。這似乎是違反直覺的,爲什麼它不具有作爲預期類型的​​參數的聲明類型?事實證明,表達可以有一個更具體的類型,這類型檢查推遲到調用點:

scala> def foo[T](t: T = "string-t") = t 
foo: [T](t: T)T 

scala> foo(1) 
res4: Int = 1 

scala> foo() 
res5: java.lang.String = string-t 

scala> foo[Int]() 
<console>:7: error: type mismatch; 
found : java.lang.String 
required: Int 
Error occurred in an application involving default arguments. 
     foo[Int]() 

如果textProvider類型不包含類型參數T,默認表達式預期的類型,你可以使用佔位符語法:

scala> def buttonGroup[T](values: Array[T], textProvider: Any => String = _.toString) = 0 
buttonGroup: [T](values: Array[T],textProvider: (Any) => String)Int 

對於命名和默認參數設計的詳細解釋,我建議盧卡斯Rytz的Scala Days presentation