2009-09-08 5 views
9

En écrivant le code suivant dans scalaParse error de tuples imbriquées dans scala

var m = Map((0,1) -> "a") 
m += ((0,2), "b") // compilation error 

J'obtiens l'erreur

 
type mismatch; 
found : Int(0) 
required: (Int, Int) 

Cependant, la modification de la syntaxe du tuple de (X,Y) à (X -> Y) œuvres

var m = Map((0,1) -> 'a) 
m += ((0,2) -> 'b) // compiles file 

Même si

((0,1).getClass == (0 -> 1).getClass) // is true 
(0,1).isInstanceOf[Tuple2[_,_]] && (0 -> 1).isInstanceOf[Tuple2[_,_]] // both true 

Pourquoi est-ce? Qu'est-ce que scala pense que mon tuple imbriqué est?

+0

I * toujours * faire la même erreur –

Répondre

10

La raison est assez simple (je pense) et a à voir avec le fait que (le trait Map):

m += (a -> b) 

est un raccourci pour:

m = m.+(t2) //where t2 is of type Tuple2[A,B] 

Il est évident que si vous utilisez une virgule dans le premier exemple, Scala interprétera cela comme étant un appel à la méthode:

m = m.+(a, b) 

Cette méthode n'existe pas sur le trait Map. Les règles d'invocation de méthode signifient que a -> b est évalué en premier (au Tuple2) et par conséquent la méthode correcte est appelée. Note: En utilisant une paire de parenthèses fonctionne très bien:

m += ((a,b)) //works just fine but less readable 
+0

j'étais en fait assez sûr que Obj Op Pred est équivalent à Pred.Op ((Pred)) déjà. Y at-il une utilisation (dans la bibliothèque standard, ou Lift) pour appeler une fonction avec deux arguments en tant qu'opérateur? (Un exemple qui a du sens bien sûr, vous pouvez toujours faire "array mise à jour (x, y)" mais ça a l'air étrange –

+0

Je suis d'accord avec vous Elazar Je pense que le compilateur devrait avoir un peu plus de sens ici –

0

Oxbow est correct. Vous pouvez utiliser une autre parenthèse pour lever l'ambiguïté, bien que:

m += (((0,2), "b")) 
+0

J'ai souligné que les parenthèses supplémentaires ont résolu le problème –