2010-10-11 16 views
8

Ich mache eine Übung in Scala und diese Val Neuzuweisung Fehler zu bekommen. Ich sehe nicht, wo ichReassignment zu einem Val in 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) 
    } 

} 

einen neuen Wert zu einem val bin Neuzuweisung und ich erhalte diesen Fehler

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

Antwort

9

b Dies ist der Name eines Parameters für Ihre Schließung ist ein val, die nicht neu zugewiesen werden kann.

foldLeft funktioniert, indem Sie den Rückgabewert eines Aufrufs des Abschlusses als Parameter b an den nächsten übergeben, also müssen Sie nur b + (p.name->p.emailAddresses) zurückgeben. (Vergessen Sie nicht die Klammern für die Priorität.)

+0

Vielen Dank, dass auch gearbeitet und ich habe nicht eine veränderbare Karte verwenden –

3

Sie Neuzuweisung val b im Ausdruck b+=p.name->p.emailAddresses.

3

unveränderbar Map hat keine += Methode. In diesem Fall übersetzt der Compiler b += p.name -> p.emailAddresses in b = b + p.name->p.emailAddresses. Da hast du es, Neuzuweisung!

+0

danken Ihnen, Ich änderte die Karte in eine veränderbare Karte und es funktionierte. Nicht sicher, ob das die richtige Lösung ist, aber –

+3

Keine Notwendigkeit, eine veränderbare Karte zu verwenden. Sie sollten stattdessen '+ =' in '+' ändern (wie bereits von @Ken Bloom vorgeschlagen). – missingfaktor

0

Wie bereits erwähnt, wird die Fehlermeldung in dem Ausdruck Ursprung ...b+=bp.name...

Aber wirklich, Sie brauchen kein foldLeft hier überhaupt zu tun, eine einfache Zuordnung sollte ausreichen. Jede Seq[K->V] kann dann über die toMap-Methode in eine Map[K,V] konvertiert werden.

Etwas wie folgt aus:

Haftungsausschluss: nicht für Tippfehler getestet usw.

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

Die Definition einer impliziten Umwandlung von 'String' in' EmailAddress' scheint ein Overkill zu sein. :) – missingfaktor

+0

Wahr, aber der Code war * soooo * boilerplatey, und breit, für den Versuch, in das StackOverflow-Fenster passen –

+0

Ich mag das DPP Zitat (aus seinem Buch): "Ich denke an implicits wie ich an Vampire denken. Sie sind sehr mächtig und sehr gefährlich, und ich lade sie nur in den Rahmen meines Programms ein, wenn es einen guten Grund dafür gibt. " –

Verwandte Themen