在Scala中重新分配给val

时间:2010-10-11 18:07:21

标签: scala scala-collections

我正在Scala中进行训练并获得此val重新分配错误。我没有看到我将新值重新分配给val

class personTest
{
  val alf = Person("Alf", 30, List(EmailAddress("alf.kristian@gmail.com")))
  val fredrik = Person("Fredrik", 33, List(EmailAddress("fredrik@vraalsen.no"), EmailAddress("fvr@knowit.no")))
  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)

4 个答案:

答案 0 :(得分:9)

b这是闭包参数的名称本身是val,无法重新分配。

foldLeft通过将闭包的一次调用的返回值作为参数b传递给下一个来工作,所以您需要做的就是返回b + (p.name->p.emailAddresses)。 (不要忘记括号的优先顺序。)

答案 1 :(得分:3)

您在表达式b中重新分配val b+=p.name->p.emailAddresses

答案 2 :(得分:3)

不可变Map没有+=方法。在这种情况下,编译器会将b += p.name -> p.emailAddresses转换为b = b + p.name->p.emailAddresses。你有它,重新分配!

答案 3 :(得分:0)

如前所述,错误消息源自表达式...b+=bp.name...

但实际上,你根本不需要在这里做一个foldLeft,一个简单的映射就足够了。然后,可以通过Seq[K->V]方法将任何Map[K,V]转换为toMap

这样的事情:

免责声明:未对拼写错误等进行测试

class personTest {
  val alf = Person(
    "Alf",
    30,
    EmailAddress("alf.kristian@gmail.com") ::
    Nil
  )

  val fredrik = Person(
    "Fredrik",
    33,
    EmailAddress("fredrik@vraalsen.no") ::
    EmailAddress("fvr@knowit.no") ::
    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
    )
  }
}