这些工作中的任何一个,没有类型注释:
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
有关命名参数和默认参数设计的详细说明,我建议使用Lucas Rytz的
Scala Days presentation
.