Переназначение в Вале в Скале - PullRequest
8 голосов
/ 11 октября 2010

Я делаю учебное упражнение в 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 ]

9 голосов
/ 11 октября 2010

b, который является именем параметра для вашего замыкания, сам по себе val, который не может быть переназначен.

foldLeft работает, принимая возвращаемое значение одного вызова замыканияв качестве параметра b к следующему, поэтому все, что вам нужно сделать, это вернуть b + (p.name->p.emailAddresses).(Не забывайте скобки за приоритет.)

3 голосов
/ 11 октября 2010

Неизменяемый Map не имеет метода +=.В этом случае компилятор переводит b += p.name -> p.emailAddresses в b = b + p.name->p.emailAddresses.Вот оно, переназначение!

3 голосов
/ 11 октября 2010

Вы переназначаете val b в выражении b+=p.name->p.emailAddresses.

0 голосов
/ 11 октября 2010

Как упоминалось ранее, сообщение об ошибке возникает в выражении ...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
    )
  }
}
...