Добавление к карте Scala внутри цикла for и условного оператора - PullRequest
6 голосов
/ 23 августа 2011

Я получаю сообщение об ошибке «error: type arguments [Any] не соответствуют чертам границ параметра типа Cloneable [+ A <: AnyRef]», «из которых я не могу сделать ни головы, ни хвосты. </p>

В частности,

var M = mutable.Map[Int, mutable.Set[Int]]()
for(i <- 1 to 100; j <- 1 to 100) {
    if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
    else {M(i) += j} 
}

(на самом деле я пытаюсь сделать что-то более сложное, но это код ошибки, откорректированный и максимально упрощенный)

И последняя строкаПриведенный выше код генерирует сообщение об ошибке.Если я урежу его дальше

for(i <- 1 to 100; j <- 1 to 100) {
    if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
}

, это сработает!

Как мне заставить работать приведенный выше код?

Ответы [ 2 ]

7 голосов
/ 23 августа 2011

Digal диагностировал проблему (не удалось объединить типы ветвей if-else), и это похоже на ошибку компилятора. Вот еще один упрощенный случай, который выдаст ошибку в REPL после длительного времени компиляции,

if (true) {
  null: collection.mutable.Map[Int, Int]
} else {
  null: collection.mutable.Set[Int]
}

Тем временем вы можете заставить свой код компилироваться с явным типом, добавленным где-то в операторе if-else,

for(i <- 1 to 100; j <- 1 to 100) {
  if(!M.contains(i)) {M += i -> mutable.Set[Int](j)}
  else {M(i) += j}: Unit 
}

Я подал вопрос здесь: https://issues.scala -lang.org / browse / SI-4938

6 голосов
/ 23 августа 2011

Я сократил ваш пример еще больше:

scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1}; 
<console>:9: error: type arguments [Any] do not conform to trait Cloneable's type parameter bounds [+A <: AnyRef]
val res17 =
    ^

Проблема возникает, когда компилятор пытается найти общий тип возврата для обеих веток: Первый -

scala> M += 1 -> mutable.Set[Int](1)
res19: scala.collection.mutable.Map[Int,scala.collection.mutable.Set[Int]] = ...

И часть "еще" -

scala> M(1) += 1
res18: scala.collection.mutable.Set[Int] = Set(1)

Если я добавлю возвращаемое значение в конец этого выражения, REPL съест его без ошибок:

scala> if(!M.contains(1)) {M += 1 -> mutable.Set[Int](1)} else {M(1) += 1}; println("hello")
hello

Поскольку тип возвращаемого выражения - Unit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...