考虑

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 输出。

对于预期类型 Double0 的类型被视为 Double , 0.0 。那是因为人们讨厌的转换范围不断扩大。

这是在求解 B1 之前。 B1 被视为 AnyVal 因为那是 A/IntDouble 的结合。

|    |-- 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,而不是让方法返回在赋值中扩展为 IntDouble

关于scala - 用 Map#getOrElse 输入奇怪的东西,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25897784/

10-14 16:19
查看更多