Scala: импорт не требуется, чтобы использовать immutable. Карта? - PullRequest
0 голосов
/ 16 мая 2018

Я изучаю Scala здесь https://scastie.scala -lang.org / iRJ8VOw7TySZ4KQ5qlWkdw .

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.SortedSet
// import scala.collection.immutable.Map // import not required to use immutable.Map

val m = Map((1 -> "a"), (2 -> "bb"))

val r = m.filter(_._1 > 1)

r // Map(2 -> bb): scala.collection.immutable.Map

println(r)

В приведенных выше кодах r имеет тип scala.collection.immutable.Map, даже еслиscala.collection.immutable.Map не импортировано, но scala.collection.mutable импортировано.

, если импортировано scala.collection.immutable.Map и scala.collection.mutable._, r равно immutable.Map.если import scala.collection.mutable._, r равно mutable.Map.

Я немного растерялся.Кто-нибудь может помочь объяснить это?Спасибо

Ответы [ 5 ]

0 голосов
/ 17 мая 2018

Здесь есть пять разных вопросов, давайте разберемся с ними один за другим.


Почему import collection.mutable, похоже, ничего не делает?

Еслимы опускаем ненужные детали из вашего фрагмента кода, мы получаем:

import scala.collection.mutable
val r = Map(2 -> 3)

Вы спросили, почему r по-прежнему scala.collection.immutable.Map.

Сначала обратите внимание, что

import scala.collection.mutable

- это не то же самое, что

import scala.collection.mutable._

Последний является импортом по шаблону (который импортирует изменяемую карту по требованию), тогда как первый импортирует только символ mutable.Поэтому в вашем коде доступен только символ mutable, но это никак не влияет на значение Map.


Откуда приходит scala.collection.immutable.Mapдаже если ничего не импортировано?

Predef всегда импортируется неявно (если вы не отключите его с помощью флага компилятора).Существует определение псевдонима типа

type Map[A, +B] = collection.immutable.Map[A, B] 

в Predef , а также прямой ярлык для сопутствующего объекта immutable.Map:

val Map: collection.immutable.Map.type 

, которыйпозволяет создавать карты с использованием Map(...) -синтаксиса без new -ключейного слова.


Почему import collection.immutable.Map имеет приоритет над import collection.mutable._?

В спецификации указывается приоритет импорта :

  1. Определения и объявления, которые являются локальными, наследуются или становятся доступными с помощью предложения пакета в той же единице компиляциигде определение имеет наивысший приоритет.
  2. Явные импорты имеют следующий наивысший приоритет.
  3. Импорт подстановочных знаков имеет следующий наивысший приоритет.
  4. Определения, доступные в предложении пакета, которого нетблок компиляции, в котором происходит определение, имеет наименьший приоритет.

Следовательно, из-за пунктов 2 и 3 явный импорт

import scala.collection.mutable.Map

имеет приоритет над подстановочным символомd import

import scala.collection.immutable._

Почему import collection.mutable._ делает Map изменяемым?

Теперь осталось уточнить последнее: почему mutable._ импорт подстановочных знаков имеет приоритет над определением в Predef?Вот короткий пример, который демонстрирует это:

import scala.collection.mutable._
val m = Map()
println(m.getClass)

Вывод (может быть, несколько удивительно):

class scala.collection.mutable.HashMap

Спецификация кажется немного неопределенной в этом вопросе, по крайней мереЯ не мог найти, где говорится, что обычный импорт с использованием подстановочных знаков затмевает определения в Predef.Однако здесь здесь написано:

Каждая единица компиляции неявно импортирует следующие пакеты в указанном порядке:

  • пакет java.lang,
  • пакет scala и
  • объект scala.Predef, если нет явного импорта верхнего уровня, который ссылается на scala.Predef.

Членыпоследующий импорт в таком порядке скрывает членов более раннего импорта.

Я думаю, что последнее предложение также охватывает импорт, который идет после scala.Predef, то есть также явный импорт с использованием подстановочных знаков.Вероятно, поэтому import scala.collection.mutable._ затмевает определения в Predef.


Что происходит в REPL?

Когда вы экспериментируете с импортом,Вы должны иметь в виду, что REPL оценивает каждую строку, как если бы она была в новом вложенном блоке.Это означает, что, например, скрипт

import scala.collection.mutable._
import scala.collection.immutable._
Map()

приведет к

error: reference to Map is ambiguous

Но если вы введете одни и те же строки в REPL одна за другой, ошибки не произойдет,и вы получите неизменный Map.Это связано с тем, что в REPL вышеприведенные строки интерпретируются как

import scala.collection.mutable._
{
  import scala.collection.immutable._
  {
    Map()
  }
}

, поэтому последний импорт имеет приоритет.Я не уверен, как Скотти справится с этим, возможно, там то же самое, так что это еще одно осложнение, которое вы должны иметь в виду.

0 голосов
/ 17 мая 2018

По по умолчанию Scala дает нам неизменную карту .Существует два способа для создания изменяемой карты :

**1.** Use import statement - *scala.collection.mutable._* to bring mutable map it into scope 
**2.** Specify the full path to *scala.collection.mutable.Map*

С импортом " import scala.collection.mutable ._ ",Вы импортируете всю доступную изменяемую коллекцию вместе с изменяемой картой .

Если вы добавляете scala.collection.immutable.Map вместе с scala.collection.mutable ._ , вы говорите компилятору scala использовать всю изменяемую коллекцию, но в случае Map используйте immutable.

0 голосов
/ 16 мая 2018

tl; др использование import scala.collection.mutable.Map


Это потому, что m является экземпляром scala.collection.immutable.Map (поведение по умолчанию). Подобное поведение в Java все в пакете java.lang неявно импортируется.

Вы импортировали пакет неизменным, это автоматически не переносит в область действия scala.collection.immutable.Map, чтобы скрыть scala.collection.mutable.Map
Для этого вам следует import scala.collection.mutable.Map

import scala.collection.mutable
val m = Map((1 -> "a"), (2 -> "bb"))
println(m.getClass)  // class scala.collection.immutable.Map$Map2

val mutableMap = mutable.Map((1->"A"), (2->"BB"))
println(mutableMap.getClass) // class scala.collection.mutable.HashMap

В качестве альтернативы

import scala.collection.mutable.Map
val m = Map((1 -> "a"), (2 -> "bb"))
println(m.getClass)  // class scala.collection.mutable.HashMap
0 голосов
/ 17 мая 2018

Первая проблема заключается в том, что Map не импортируется из scale.collection.mutable, поскольку существует проблема с вашим оператором import.

Измените

import scala.collection.mutable

на

import scala.collection.mutable._

или

import scala.collection.mutable.Map

и Map будет mutable.Map.

При импорте scale.collection.immutable.Map и scala.collection.mutable._ immutable Mapпобеждает, потому что это более конкретно.Таким образом, выигрывает самый конкретный import, и в случае ничьей вы получите ошибку компилятора.

0 голосов
/ 16 мая 2018

По умолчанию карта в Scala является неизменной. Вы не импортируете mutable.Map, поэтому он все еще неизменен. Если вы импортируете это так, оно должно работать:

import scala.collection.mutable.Map

если импортировать scala.collection.immutable.Map и scala.collection.mutable. , r является неизменным. Карта. если импорт scala.collection.mutable. , r является изменяемым. Карта.

Победит наиболее квалифицированный оператор импорта.

...