2010-10-11 7 views
8

Je fais un exercice d'entraînement dans Scala et j'obtiens cette erreur de réaffectation. Je ne vois pas où je suis réaffectant une nouvelle valeur à un valRéaffectation à un val dans Scala

class personTest 
{ 
    val alf = Person("Alf", 30, List(EmailAddress("[email protected]"))) 
    val fredrik = Person("Fredrik", 33, List(EmailAddress("[email protected]"), EmailAddress("[email protected]"))) 
    val johannes = Person("Johannes", 0, Nil) 

    val persons = List(alf, fredrik, johannes) 

    @Test 
    def testNameToEmailAddress 
    { 
    // Create a map from each persons name to their e-mail addresses, 
    // filtering out persons without e-mail addresses 
    // Hint: First filter list, then use foldLeft to accumulate... 
    val emptyMap: Map[String, List[EmailAddress]] = Map() 

    val nameToEmail = persons.filter(_.emailAddresses.length>0).foldLeft(emptyMap)((b,p)=> b+=p.name->p.emailAddresses) 

    assertEquals(Map(alf.name -> alf.emailAddresses, fredrik.name -> fredrik.emailAddresses), nameToEmail) 
    } 

} 

et je reçois cette erreur

error: reassignment to val 
val nameToEmail = persons.filter(_.emailAddresses.length>0).foldLeft(emptyMap)((b,p)=> b+=p.name->p.emailAddresses) 

Répondre

9

b qui est le nom d'un paramètre à votre fermeture est lui-même val, qui ne peut pas être réaffecté.

foldLeft fonctionne en prenant la valeur de retour d'une invocation de la fermeture comme le paramètre b au suivant, donc tout ce que vous devez faire est de retourner b + (p.name->p.emailAddresses). (Ne pas oublier les parenthèses pour la précédence.)

+0

Merci, qui a travaillé aussi et je ne devais pas utiliser une carte mutable –

3

Vous réassignez val b dans l'expression b+=p.name->p.emailAddresses.

3

La variable Map ne possède pas la méthode +=. Dans ce cas, le compilateur traduit b += p.name -> p.emailAddresses en b = b + p.name->p.emailAddresses. Là vous l'avez, réaffectation!

+0

Merci, J'ai changé la carte en une carte mutable et cela a fonctionné. Je ne sais pas si c'est la bonne solution si –

+3

Pas besoin d'utiliser une carte modifiable. Vous devriez remplacer '+ =' par '+' (comme déjà suggéré par @Ken Bloom). – missingfaktor

0

Comme mentionné précédemment, le message d'erreur est originaire de l'expression ...b+=bp.name...

Mais vraiment, vous n'avez pas besoin de faire un foldLeft tout ici, une cartographie simple devrait être suffisant. Tout Seq[K->V] peut ensuite être converti en Map[K,V] via la méthode toMap.

Quelque chose comme ceci:

Avertissement: non testé pour les fautes de frappe, etc.

class personTest { 
    val alf = Person(
    "Alf", 
    30, 
    EmailAddress("[email protected]") :: 
    Nil 
) 

    val fredrik = Person(
    "Fredrik", 
    33, 
    EmailAddress("[email protected]") :: 
    EmailAddress("[email protected]") :: 
    Nil) 

    val johannes = Person(
    "Johannes", 
    0, 
    Nil) 

    val persons = List(alf, fredrik, johannes) 

    @Test 
    def testNameToEmailAddress { 

    val nameToEmailMap = 
     persons.view filter (!_.emailAddresses.isEmpty) map { 
     p => p.name -> p.emailAddresses 
     } toMap 

    assertEquals(
     Map(
     alf.name -> alf.emailAddresses, 
     fredrik.name -> fredrik.emailAddresses 
    ), 
     nameToEmailMap 
    ) 
    } 
} 
+1

La définition d'une conversion implicite de 'String' à' EmailAddress' semble être une surcharge. :) – missingfaktor

+0

Vrai, mais le code était * sooooo * boilerplatey, et large, pour essayer de s'intégrer dans la fenêtre StackOverflow –

+0

J'aime la citation DPP (de son livre): "Je pense à implicits comme je pense à des vampires. très puissant et très dangereux, et je les invite seulement dans la portée de mon programme quand il y a une très bonne raison. " –

Questions connexes