2010-10-11 14 views
8

Robię ćwiczenie treningowe w Scali i otrzymuję ten błąd zmiany przypisania. Nie widzę, gdzie jestem realokacja nową wartość do valPrzeniesienie do val w 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) 
    } 

} 

i otrzymuję ten błąd

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

Odpowiedz

9

b Która nazwa parametru do zamknięcia jest sama w sobie val, której nie można ponownie przypisać.

foldLeft prace przy przejściu wartości zwracanej jednym wywołaniu zamknięcia jako parametr b do następnego, więc wszystko co musisz zrobić, to wrócić b + (p.name->p.emailAddresses). (Nie zapomnij o nawiasach dla pierwszeństwa.)

+0

Dziękuję, że pracował też i nie trzeba używać zmienny mapę –

3

Ty realokacja val b w wyrażeniu b+=p.name->p.emailAddresses.

3

Niezmienny Map nie ma metody +=. W takim przypadku kompilator tłumaczy b += p.name -> p.emailAddresses na b = b + p.name->p.emailAddresses. Masz to, zmiana przydziału!

+0

dziękuję Zmieniłem mapę na zmienną mapę i zadziałało. Nie jestem pewien, czy to jest właściwe rozwiązanie. –

+3

Nie trzeba używać map zmiennych. Zamiast tego powinieneś zmienić '+ =' na '+ '(jak już zasugerował @Ken Bloom). – missingfaktor

0

Jak wcześniej wspomniano, komunikat o błędzie jest pochodzący z wypowiedzi ...b+=bp.name...

Ale naprawdę, nie trzeba się robić foldLeft tutaj w ogóle, to proste mapowanie powinno wystarczyć. Dowolny Seq[K->V] można następnie przekonwertować na Map[K,V] za pomocą metody toMap.

coś takiego:

disclaimer: nie testowane pod kątem literówek itp

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

Definiowanie niejawnej konwersji z 'String' na' EmailAddress' wygląda na przesadę. :) – missingfaktor

+0

To prawda, ale kod był * taki *oo * boilerplatey, i szeroki, próbując dopasować się do okna StackOverflow –

+0

Podoba mi się cytat z DPP (z jego książki): "Myślę o implikacjach jak myślę o wampirach. bardzo potężny i bardzo niebezpieczny, a ja tylko zapraszam ich do zakresu mojego programu, gdy istnieje bardzo dobry powód ". –

Powiązane problemy