Scala:使用 immutable.Map 不需要导入?
Scala: import not required to use immutable.Map?
我在这里学习 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
。
我有点困惑。谁能帮忙解释一下?谢谢
默认情况下,Scala 中的 Map 是不可变的。
您不导入 mutable.Map,因此它仍然是不可变的。
如果你像这样导入它应该可以工作:
import scala.collection.mutable.Map
if import scala.collection.immutable.Map and
scala.collection.mutable., r is immutable.Map. if import
scala.collection.mutable., r is mutable.Map.
最符合条件的导入语句获胜。
tl;dr 使用 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
第一个问题是 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
获胜,在平局的情况下,您将收到编译器错误。
通过默认 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*
通过导入“导入scala.collection.mutable._”,您将导入所有可用的可变集合以及可变映射 .
如果您将 scala.collection.immutable.Map 与 scala.collection.mutable._ 一起添加,则 Scala 编译器使用所有可变集合,但对于 Map,使用不可变集合。
这里有五个不同的问题,让我们一一解决。
为什么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._
后者是通配符导入(按需导入可变Map),而前者只导入符号[=25=]。因此,在您的代码中,只有符号 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._
?
specification states about the precedence of imports:
- Definitions and declarations that are local, inherited, or made available by a package clause in the same compilation unit where the definition occurs have highest precedence.
- Explicit imports have next highest precedence.
- Wildcard imports have next highest precedence.
- Definitions made available by a package clause not in the compilation unit where the definition occurs have lowest precedence.
因此,由于第 2 点和第 3 点,显式导入
import scala.collection.mutable.Map
优先于通配符导入
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 中的定义。但是,here 它说:
Every compilation unit implicitly imports the following packages, in the given order:
- the package java.lang,
- the package scala, and
- the object scala.Predef, unless there is an explicit top-level import that references scala.Predef.
Members of a later import in that order hide members of an earlier import.
我认为最后一句话也涵盖了 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()
}
}
以便最后一次导入优先。我不确定 Scastie 是如何处理它的,可能它在那里是一样的,所以这是你必须记住的一个额外的并发症。
我在这里学习 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
。
我有点困惑。谁能帮忙解释一下?谢谢
默认情况下,Scala 中的 Map 是不可变的。 您不导入 mutable.Map,因此它仍然是不可变的。 如果你像这样导入它应该可以工作:
import scala.collection.mutable.Map
if import scala.collection.immutable.Map and scala.collection.mutable., r is immutable.Map. if import scala.collection.mutable., r is mutable.Map.
最符合条件的导入语句获胜。
tl;dr 使用 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
第一个问题是 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
获胜,在平局的情况下,您将收到编译器错误。
通过默认 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*
通过导入“导入scala.collection.mutable._”,您将导入所有可用的可变集合以及可变映射 .
如果您将 scala.collection.immutable.Map 与 scala.collection.mutable._ 一起添加,则 Scala 编译器使用所有可变集合,但对于 Map,使用不可变集合。
这里有五个不同的问题,让我们一一解决。
为什么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._
后者是通配符导入(按需导入可变Map),而前者只导入符号[=25=]。因此,在您的代码中,只有符号 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._
?
specification states about the precedence of imports:
- Definitions and declarations that are local, inherited, or made available by a package clause in the same compilation unit where the definition occurs have highest precedence.
- Explicit imports have next highest precedence.
- Wildcard imports have next highest precedence.
- Definitions made available by a package clause not in the compilation unit where the definition occurs have lowest precedence.
因此,由于第 2 点和第 3 点,显式导入
import scala.collection.mutable.Map
优先于通配符导入
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 中的定义。但是,here 它说:
Every compilation unit implicitly imports the following packages, in the given order:
- the package java.lang,
- the package scala, and
- the object scala.Predef, unless there is an explicit top-level import that references scala.Predef.
Members of a later import in that order hide members of an earlier import.
我认为最后一句话也涵盖了 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()
}
}
以便最后一次导入优先。我不确定 Scastie 是如何处理它的,可能它在那里是一样的,所以这是你必须记住的一个额外的并发症。