Chacune de ces travaux, sans annotation de type:
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
Mais pourquoi ne fonctionnent pas vos variations?
Le premier est en fait pas valide Scala dans un contexte:
scala> (t: Any => t.toString)
<console>:1: error: ';' expected but ')' found.
(t: Any => t.toString))
^
La deuxième expression _.toString
utilise la syntaxe de l'espace réservé pour les fonctions anonymes, et ne fonctionne que si l'expression a un type attendu.
scala> def foo[T] = { (_.toString) : (T => String) }
foo: [T](T) => String
Le problème est que l'expression par défaut pour un paramètre dont le type dépend d'un paramètre de type n'a pas de type attendu. Cela semble contre-intuitif, pourquoi n'aurait-il pas le type déclaré de l'argument comme le type attendu? Il se trouve que l'expression peut avoir un type plus spécifique, et que la vérification de type est reporté à l'appel site:
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]()
Si le type de textProvider
ne comprend pas le paramètre de type T
, l'expression par défaut a un type attendu, et vous pouvez utiliser la syntaxe de l'espace réservé:
scala> def buttonGroup[T](values: Array[T], textProvider: Any => String = _.toString) = 0
buttonGroup: [T](values: Array[T],textProvider: (Any) => String)Int
Pour une explication détaillée de la conception des paramètres nommés et par défaut, je recommande Scala Days presentation de Lucas Rytz.