考虑
scala> val m = Map('a -> 3, 'b -> 4)
m: scala.collection.immutable.Map[Symbol,Int] = Map('a -> 3, 'b -> 4)
scala> val d: Double = m.getOrElse('c, 0)
<console>:8: error: type mismatch;
found : AnyVal
required: Double
val d: Double = m.getOrElse('c, 0)
^
scala> m.getOrElse('c, 0)
res0: Int = 0
scala> m.getOrElse('a, 0)
res1: Int = 3
为什么 Scala 认为
getOrElse
调用返回 AnyVal
,即使它显然返回 Int
?此外,即使这失败并出现相同的错误:
scala> val x: Double = m.getOrElse('a, 0): Double
<console>:8: error: type mismatch;
found : AnyVal
required: Double
val x: Double = m.getOrElse('a, 0): Double
然而,这有效:
scala> val x: Double = m.getOrElse('a, 0): Int
x: Double = 3.0
这发生在 2.11.x 上;我没有在 2.10.x 上试过。
最佳答案
我正在努力更好地阅读 -Ytyper-debug
输出。
对于预期类型 Double
, 0
的类型被视为 Double
, 0.0
。那是因为人们讨厌的转换范围不断扩大。
这是在求解 B1
之前。 B1
被视为 AnyVal
因为那是 A
/Int
和 Double
的结合。
| |-- Double TYPEmode (site: value d in $iw)
| | \-> Double
| |-- m.getOrElse(scala.Symbol("c"), 0) : pt=Double BYVALmode-EXPRmode (site: value d in $iw)
| | |-- m.getOrElse BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value d in $iw)
| | | |-- m EXPRmode-POLYmode-QUALmode (silent: value d in $iw)
| | | | \-> m.type (with underlying type scala.collection.immutable.Map[Symbol,Int])
| | | [adapt] [B1 >: B](key: A, default: => B1)B1 adapted to [B1 >: B](key: A, default: => B1)B1
| | | \-> (key: Symbol, default: => B1)B1
| | |-- scala.Symbol("c") : pt=Symbol BYVALmode-EXPRmode-POLYmode (site: value d in $iw)
| | | |-- scala.Symbol BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value d in $iw)
| | | | |-- scala.Symbol.apply BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value d in $iw)
| | | | | \-> (name: String)Symbol
| | | | [adapt] Symbol.type adapted to (name: String)Symbol
| | | | \-> (name: String)Symbol
| | | |-- "c" : pt=String BYVALmode-EXPRmode (silent: value d in $iw)
| | | | \-> String("c")
| | | \-> Symbol
| | |-- 0 : pt=Double EXPRmode-POLYmode (site: value d in $iw)
| | | \-> Double(0.0)
| | solving for (B1: ?B1)
<console>:8: error: type mismatch;
found : AnyVal
required: Double
val d: Double = m.getOrElse('c, 0)
^
| | \-> <error>
此外,
-xprint:typer
显示m.getOrElse[AnyVal](scala.Symbol.apply("c"), 0.0);
使用参数的预期类型对 args 进行类型检查的 spec explains(情况 3 方法),这就是为什么在那里转换为
Double
,而不是让方法返回在赋值中扩展为 Int
的 Double
。关于scala - 用 Map#getOrElse 输入奇怪的东西,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25897784/