2010-10-11 62 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