2010-05-20 5 views
1

Dans Scala 2.8.0 RC 2 cette définition:Scala 2.8: inférence de type de fonctions anonymes comme paramètres par défaut

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

donne le message d'erreur:

not found: valeur t

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

donne

manquant type de paramètre pour la fonction élargie {}

Seulement ceci fonctionne ((x 1 $) => x 1 $ {} toString {}.):

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

Pourquoi?

Répondre

4

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.

Questions connexes