Почему я должен явно указать Tuple2 (a, b), чтобы иметь возможность использовать Map add в foldLeft? - PullRequest
1 голос
/ 09 мая 2011

Я хочу создать карту по имени, содержащую количество вещей с этим именем.У меня есть список вещей с именем, который может содержать более одного предмета с одинаковым именем.Закодированный таким образом, я получаю сообщение об ошибке "несоответствие типов; найдено: Требуется строка: (String, Int)":

//variation 0, produces error 
(Map[String, Int]() /: entries)((r, c) => { r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })

Это сбивает меня с толку, поскольку я (a, b) был Tuple2 и поэтому подходитиспользовать с картой добавить.Любой из следующих вариантов работает должным образом:

//variation 1, works
(Map[String, Int]() /: entries)((r, c) => { r + Tuple2(c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
//variation 2, works
(Map[String, Int]() /: entries)((r, c) => { 
    val e = (c.name, if (r.contains(c.name)) (c.name) + 1 else 1) })
    r + e

Мне неясно, почему возникла проблема с моей первой версией;может кто-нибудь посоветовать.Я использую Scala-IDE 2.0.0 beta 2 для редактирования исходного кода;ошибка из окна «Проблемы затмения».

Ответы [ 3 ]

3 голосов
/ 09 мая 2011

Потому что + используется для объединения строк с строками.В этом случае скобки используются не для обозначения кортежа, а для обозначения параметра.

Scala использовала + для других вещей, что приводило к возникновению всевозможных проблем, как и та, о которой вы упоминали.

Заменить + на updated или использовать -> вместо ,.

3 голосов
/ 09 мая 2011

При передаче одного аргумента кортежа в метод, используемый с нотацией оператора, такой как ваш метод +, вы должны использовать двойные скобки:

(Map[String, Int]() /: entries)((r, c) => { r + ((c.name, r.get(c.name).map(_ + 1).getOrElse(1) )) })

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

1 голос
/ 09 мая 2011
r + (c.name, if (r.contains(c.name)) (c.name) + 1 else 1)

анализируется как

r.+(c.name, if (r.contains(c.name)) (c.name) + 1 else 1)

Таким образом, компилятор ищет метод + с 2 аргументами для Map и не находит его. Форма, которую я предпочитаю двойным скобкам (как предлагает Жан-Филипп Пелле):

r + (c.name -> if (r.contains(c.name)) (c.name) + 1 else 1)

UPDATE:

если пеллет верен, лучше написать

r + (c.name -> r.getOrElse(c.name, 0) + 1)

(и, конечно, решение Джеймса Ири выражает то же самое намерение еще лучше).

...