【问题标题】:What is the concept of "weak conformance" in Scala?Scala中“弱一致性”的概念是什么?
【发布时间】:2011-03-06 21:09:06
【问题描述】:

我最近刚刚遇到“弱一致性”一词(在 Stack Overflow 用户 retronymHow to set up implicit conversion to allow arithmetic between numeric types? 的回答中)。

这是什么?

【问题讨论】:

    标签: scala scala-2.8


    【解决方案1】:

    根据 Scala 语言规范 2.8:
    http://www.scala-lang.org/archives/downloads/distrib/files/nightly/pdfs/ScalaReference.pdf

    3.5.3 弱一致性
    在某些情况下,Scala 使用更一般的一致性关系。 A型S弱 符合类型 T ,写作 S <:w t s> 字节 <:w> 字节 <:w> 短 <:w int> 整数 <:w> 长 <:w> 浮点 <:w> 弱最小上界是弱一致性的最小上界。

    【讨论】:

    • 我很确定Char 也符合Int
    【解决方案2】:

    为了完成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 日):

    您在重载决议中发现了弱一致性规则的严重意外副作用。
    问题是重载方法的参数需要弱一致性,而结果类型需要强一致性.

    如果结果类型是浮点数,这有利于Int 上的Float =&gt; Float 加法方法而不是Int =&gt; Int 方法。
    我试图在更改为弱一致性时保持保守,因为我只在看起来绝对必要的情况下才需要弱一致性。
    但现在看来,保守导致了我们正在研究的问题!

    又一个 Scala RC 版本 ;)


    this thread by Martin Odersky (June 22d)确认:

    所以到目前为止,RC7 将与 RC6 相比有三个变化:

    1. val x: Double = 10/3 将给出3.0,而不是3.3333333 - 这就是我提到的回归
    2. [...]
    3. [...]

    就是这样。我们现在的首要任务是尽快推出 2.8,同时避免非常糟糕的回归,例如上面的 (1)。

    时间线:

    • 我们将再等一周以获取有关 RC6 的反馈。
    • 我们将在下周初推出 RC7。
      如果没有出现进一步的问题,RC7 将在发布 10-14 天后变成 2.8 最终版本。

    (我相信是 7 月 12 日左右,但这个猜测是我一个人的猜测;))

    【讨论】:

      【解决方案3】:

      3.5.3 弱一致性 在某些情况下,Scala 使用更通用的 一致性关系。 A型S弱 符合类型 T ,写作 S <:>w T , 如果 S <: t s>

      • 字节<:>w短
      • 字节<:>w字符
      • 短 <:>w Int
      • Int <:>w Long
      • 长 <:>w 浮点数
      • 浮点数<:>w双数

      弱最小上界是 关于弱的最小上界 一致性。

      这个用在什么地方?一方面,它决定了if 表达式的类型:

      条件表达式的类型 是 e2 和 e3 类型的弱最小上界(第 3.5.3 节)

      在 Scala 2.7.x 中,这将是 AnyVal 类型,IntDouble 的最小上限。在 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 中定义。预期类型是 原始数字类型 Byte、Short 或 Char,表达式 e 是 适合范围内的整数文字 该类型的,它被转换为 该类型中的相同文字。

      scala> 1: Double
      res10: Double = 1.0
      

      更新

      正如 Daniel 所指出的,规范对于哪些类型具有弱一致性是错误的。让我们问问编译器本身:

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-24
        • 2013-09-17
        • 2011-01-15
        相关资源
        最近更新 更多