2014-10-20 2 views
4

Я занимаюсь программированием в Scala, 2nd Edition (фантастическая книга, намного лучше, чем сайт scala для объяснения вещей в не-ракетно-научном стиле) и Я заметил эту ... странность при переходе на Неизменяемые и Mutable Sets.Scala Immutable Set является Mutable при объявлении как var

Он заявляет следующее в качестве неизменного набора

var jetSet=Set("Boeing", "Airbus") 
jetSet+="Lear" 
println(jetSet.contains("Cessna")) 

А потом заявляет, что только Изменяемые наборы определяют + = метод. Хорошо, что имеет смысл. Проблема в том, что этот код работает. И тип набора, созданный при тестировании в REPL, на самом деле является неизменяемым, но он имеет метод + =, определенный на нем, и он отлично функционирует. Вот

scala> var a = Set("Adam", "Bill") 
a: scala.collection.immutable.Set[String] = Set(Adam, Bill) 

scala> a += "Colleen" 

scala> println(a) 
Set(Adam, Bill, Colleen) 

scala> a.getClass 
res8: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3 

Но если я объявляю набор быть вал, Неизменное набор созданных не имеют + = метод определен

scala> val b = Set("Adam", "Bill") 
b: scala.collection.immutable.Set[String] = Set(Adam, Bill) 

scala> b += "Colleen" 
<console>:9: error: value += is not a member of scala.collection.immutable.Set[String] 
      b += "Colleen" 

Что здесь происходит? Оба они утверждаются как неизменяемый набор, но тот, который объявлен var, имеет доступ к методу + = и может использовать его.

Кроме того, когда я звала метод GetClass на вар непреложных Set я заметил что-то странное ....

scala> a.getClass 
res10: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set3 

scala> a += "One" 

scala> a.getClass 
res12: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.Set$Set4 

scala> a += "Two" 

scala> a.getClass 
res14: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet 

scala> a += "Tree" 

scala> a.getClass 
res16: Class[_ <: scala.collection.immutable.Set[String]] = class scala.collection.immutable.HashSet$HashTrieSet 

scala> a 
res17: scala.collection.immutable.Set[String] = Set(One, Tree, Bill, Adam, Two, Colleen) 

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

+1

«Set» неизменен, но 'a' изменен, добавление элемента в набор создает новый набор, а результат присваивается' a', если 'a' является val, он неизменен, и вы не может переназначить его. –

ответ

12

Что изменилось, это не Set, это ссылка на него.

a += "Colleen" 

возвращает новый неизменяемый набор, назначенный для изменяемого переменной a

Скала выполняет синтаксический преобразование, превращая выражение в

a = a + "Colleen" 

в случае += не определен (как в случай непреложного Set)

Ясно += не имеет смысла, когда a - это val, так как вы не можете переназначить его, поэтому это запрещено.

Вот отрывок взят из программирования в Scala (раздел 17.3)

Чтобы было легче перейти от непреложного изменяемых коллекций, и наоборот, Scala предоставляет некоторые синтаксический сахар. Несмотря на то, что неизменяемые наборы и карты не поддерживают истинный метод +=, Scala дает полезную альтернативную интерпретацию для +=. Всякий раз, когда вы пишете a += b и a не поддерживает метод с именем +=, Scala будет пытаться интерпретировать его как a = a + b

Если вы продолжаете читать в этом разделе вы найдете более подробное объяснение с примерами.

+3

Вы также должны указать синтаксический перевод сахара для '+ =', если он не определен в самом классе. – Kigyo

+0

@Kigyo справедливой пункт, сделано. –

+0

Ah Спасибо за подтверждение того, что это синтаксический сахар. Я думал, что это происходит, но не уверен. Проблема, с которой я столкнулась, заключалась в том, что пример в книге, которую я читал, приведен в главе 3, и явное объяснение не было сделано до 17-й главы (чего мне еще не удалось достичь). Они должны были использовать этот аспект или использовать другой пример. Ну что ж. –

Смежные вопросы