2010-10-11 66 views
8

我正在Scala中進行一次培訓練習並獲取此val重新分配錯誤。我沒有看到我的重新分配新值VAL重新分配到Scala中的val

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) 
    } 

} 

,我得到這個錯誤

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

回答

9

b這是你的閉包參數的名稱本身是一個val,它不能被重新分配。

foldLeft通過將封閉的一次調用的返回值作爲參數b傳遞給下一個來工作,所以您只需要返回b + (p.name->p.emailAddresses)即可。 (不要忘記括號中的優先順序。)

+0

謝謝你,工作太,我沒有使用可變地圖 – 2010-10-11 18:50:38

3

你在表達b+=p.name->p.emailAddresses重新分配VAL b

3

不可變Map沒有+=方法。在這種情況下,編譯器將b += p.name -> p.emailAddresses轉換爲b = b + p.name->p.emailAddresses。你有它,重新分配!

+0

謝謝你,我改變了地圖到一個可變的地圖,它的工作。不知道這是否是正確的解決方案,儘管 – 2010-10-11 18:46:24

+3

不需要使用可變映射。您應該將'+ ='改爲'+'(正如@Ken Bloom所建議的那樣)。 – missingfaktor 2010-10-11 19:01:46

0

正如前面提到的,錯誤消息源自表達...b+=bp.name...

但實際上,你並不需要在這裏做一個foldLeft可言,一個簡單的映射應該夠了。然後可以通過toMap方法將任何Seq[K->V]轉換爲Map[K,V]

事情是這樣的:

免責聲明:錯別字沒有測試等

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

定義從'String'到'EmailAddress'的隱式轉換似乎是一種矯枉過正。 :) – missingfaktor 2010-10-11 19:05:30

+0

是的,但代碼是* sooooo * boilerplatey,並且適合放入StackOverflow窗口 – 2010-10-11 19:33:22

+0

我喜歡DPP的引用(來自他的書):「我想到像我認爲的吸血鬼這樣的暗示,他們是非常強大和非常危險,只有在有很好的理由時,我纔會邀請他們加入我的項目範圍。「 – 2010-10-11 19:46:53