我刚刚遇到“弱一致性”一词(在Stack Overflow用户retronym对 How to set up implicit conversion to allow arithmetic between numeric types? 的回答中)。
这是什么?
答案 0 :(得分:20)
3.5.3弱一致性在某些情况下,Scala使用更一般的 一致性关系。 S型弱 符合类型T,写为S<: w T. ,如果S<:T或S和T都是 原始数字类型和S先于 T按以下顺序排列。
弱的最小上限是a 关于弱的最小上限 一致性。
这在哪里使用?首先,它确定了if
表达式的类型:
条件表达式的类型 是e2和e3
类型的弱最小上界(§3.5.3)
在Scala 2.7.x中,这类似于AnyVal
类型,Int
和Double
的最低限度。在2.8.x中,它键入为Double
。
scala> if (true) 1 else 1d
res0: Double = 1.0
类似地:
scala> try { 1 } catch { case _ => 1.0 }
res2: Double = 1.0
scala> (new {}: Any) match { case 1 => 1; case _ => 1.0 }
res6: Double = 1.0
scala> def pf[R](pf: PartialFunction[Any, R]): PartialFunction[Any, R] = pf
pf: [R](pf: PartialFunction[Any,R])PartialFunction[Any,R]
scala> pf { case 1 => 1; case _ => 1d }
res4: PartialFunction[Any,Double] = <function1>
它使用的另一个地方是类型推断:
scala> def foo[A](a1: A, a2: A): A = a1
foo: [A](a1: A,a2: A)A
scala> foo(1, 1d)
res8: Double = 1.0
scala> def foos[A](as: A*): A = as.head
foos: [A](as: A*)A
scala> foos(1, 1d)
res9: Double = 1.0
还有简单的数字扩展:
数字扩展。如果e有一个原语 弱符合的数字类型 (§3.5.3)到期望的类型,它是 使用一个扩展到预期的类型 的 6.26隐式转换97数字转换方法toShort,toChar, toInt,toLong,toFloat,toDouble 在第12.2.1节中定义。预期的类型是 原始数字类型字节,短或 Char,表达式e是 范围内的整数文字拟合 那种类型,它被转换为 该类型的文字相同。
scala> 1: Double
res10: Double = 1.0
<强>更新强>
正如丹尼尔所指出的,关于哪些类型的弱一致性,规范是错误的。让我们问编译器本身:
scala> :power
** Power User mode enabled - BEEP BOOP **
** scala.tools.nsc._ has been imported **
** New vals! Try repl, global, power **
** New cmds! :help to discover them **
** New defs! Type power.<tab> to reveal **
scala> settings.maxPrintString = 10000
scala> import global.definitions._
import global.definitions._
scala> (for{c1 <- ScalaValueClasses;
c2 <- ScalaValueClasses
isNSC = isNumericSubClass(c1, c2)
if isNSC
} yield ("isNumericSubClass (%s, %s) = %b" format (c1, c2, isNSC))).mkString("\n")
res5: String =
isNumericSubClass (class Byte, class Byte) = true
isNumericSubClass (class Byte, class Short) = true
isNumericSubClass (class Byte, class Int) = true
isNumericSubClass (class Byte, class Long) = true
isNumericSubClass (class Byte, class Float) = true
isNumericSubClass (class Byte, class Double) = true
isNumericSubClass (class Short, class Short) = true
isNumericSubClass (class Short, class Int) = true
isNumericSubClass (class Short, class Long) = true
isNumericSubClass (class Short, class Float) = true
isNumericSubClass (class Short, class Double) = true
isNumericSubClass (class Int, class Int) = true
isNumericSubClass (class Int, class Long) = true
isNumericSubClass (class Int, class Float) = true
isNumericSubClass (class Int, class Double) = true
isNumericSubClass (class Long, class Long) = true
isNumericSubClass (class Long, class Float) = true
isNumericSubClass (class Long, class Double) = true
isNumericSubClass (class Char, class Int) = true
isNumericSubClass (class Char, class Long) = true
isNumericSubClass (class Char, class Char) = true
isNumericSubClass (class Char, class Float) = true
isNumericSubClass (class Char, class Double) = true
isNumericSubClass (class Float, class Float) = true
isNumericSubClass (class Float, class Double) = true
isNumericSubClass (class Double, class Double) = true
答案 1 :(得分:5)
要完成Sandor's answer,2.8中的新功能仍在烘焙(并已修复)。
在this thread中,Esser发现了令人讨厌的副作用:
scala> val a= 10
a: Int = 10
scala> val b= 3
b: Int = 3
scala> if (b!=0) a/b else Double.NaN
res0: Double = 3.0
scala> def div1(a: Int, b: Int) = if (b!=0) a/b else Double.NaN
div1: (a: Int,b: Int)Double
scala> def div2(a: Int, b: Int): Double = if (b!=0) a/b else Double.NaN
div2: (a: Int,b: Int)Double
scala> div1(10,3)
res1: Double = 3.0
scala> div2(10,3)
res2: Double = 3.3333333333333335
似乎很有趣,因为隐式找到的结果类型是
Double
,结果是3.0 如果明确给出Double,则结果为3.33 ...
在this thread,Martin Odersky补充道(6月21日):
您在重载决议时发现了弱一致性规则的严重意外副作用 问题是重载方法的参数需要弱化,而结果类型需要强烈符合。
如果结果类型为Float,则优先于
Float => Float
上的Int
Int => Int
添加方法。 我试图保持对弱一致性的改变,因为我只是在看起来绝对必要的情况下才要求弱一致性 但现在看来,保守派导致了我们正在关注的问题!
另一个Scala RC发布;)
在this thread by Martin Odersky (June 22d)中确认:
所以RC7到目前为止还有三次改变来自RC6:
val x: Double = 10/3
会提供3.0
,而非3.3333333
- 这就是我提到的回归- [...]
- [...]
醇>就是这样。我们现在的优先事项是尽可能快地推出2.8,同时避免真正糟糕的回归,例如上面的(1)。
时间表:
- 我们将再等一周,以获得有关RC6的反馈。
- 我们将在下周初推出RC7 如果没有其他问题出现,RC7将在发布后的最后10-14天变为2.8。
(所以7月12日左右,我相信,但这个猜测只有我自己;))
答案 2 :(得分:4)
根据Scala lang规范2.8:
http://www.scala-lang.org/archives/downloads/distrib/files/nightly/pdfs/ScalaReference.pdf
3.5.3一致性差弱
在某些情况下,Scala使用更一代的一致性关系。 S型弱
符合类型T,写入S&lt;:W T,如果S&lt;:T或S和T都是原始数字
类型和S在以下顺序中位于T之前
Byte&lt;:w短暂的
字节&lt;:w字符
简短&lt;:w Int
Int&lt;:w长
长&lt;:w Float
Float&lt;:w双
弱上限是弱上一致性的最小上界。