为什么"for/comprehension"表达式与(!)赋值操作之间的数值类型的隐式转换不一致?

IOD*_*DEV 1 numerical types scala list-comprehension implicit-conversion

为什么"for/comprehension"表达式的数值类型的desugaring和隐式转换与(!)赋值操作相比不一致?

我相信对此有很多一般性的观点,但我无法找出当前行为的简明和合理的解释.[参考:"Scala for/comprehension的行为......" ]为了正确起见,下面的所有翻译都是使用scala编译器生成的("scalac -Xprint:typer -e")

例如,在隐式数字赋值转换期间,Destination类型占主导地位:

来源:var l:Long = 0
结果:val l: Long = 0L

来源:var l:Long = 0.toInt
结果:var l: Long = 0.toInt.toLong

在"for/comprehension"表达式的隐式转换期间,Source类型占主导地位:

来源:for (i:Long <- 0 to 1000000000L) { }
结果:0.to(1000000000L).foreach(((i: Long) => ()))

来源:for (i <- 0L to 1000000000L) { }
结果:scala.this.Predef.longWrapper(0L).to(1000000000L).foreach[Unit](((i: Long) => ()))

Dan*_*ral 5

发生了两件完全不同的事情.首先,任务:

val l: Long = 0
Run Code Online (Sandbox Code Playgroud)

我们有一个Int被分配给a Long.这应该是不可能的,除非有从隐式转换IntLong,我们可以验证这样的:

scala> implicitly[Int => Long]
res1: Int => Long = <function1>
Run Code Online (Sandbox Code Playgroud)

由于存在这样的转换,因此应用该转换.

接下来,for-comprehension:

for (i:Long <- 0 to 1000000000L) { }
Run Code Online (Sandbox Code Playgroud)

这不起作用,因为to调用的方法Int(实际上是scala.runtime.RichInt通过隐式转换调用)只允许Int参数,而不是Long参数.

to调用a Long(RichLong)的方法确实允许一个Long参数,但有两个原因可以解释为什么它不适用于上面的表达式:

  1. 要进入RichLongto方法中,Int就必须先转换成一个Long,然后进入一个RichLong,和Scala不适用两次链式隐式转换,直到永远.它只能转换IntRichInt或转换为Long,而不是Int转换LongRichLong.
  2. 要应用这种转换,首先必须有一些指示Long,而没有.在i: Long不参考的类型0 to 1000000000L,而l: Long确实提到的类型0中的第一个例子.