为什么Scala强制类型从Char到Double?

时间:2016-09-16 06:47:59

标签: scala

以下代码

 ;; define *xx* so that it can be "seen" globally
 (defparameter *xx* 23)
 ;; establish a variable which is only "seen" locally
 (let ((xx 0))
   (format t "xx: ~S~%" xx)
   (incf xx)
   (format t "xx: ~S~%" xx))

结果

object testType extends App {
  def func(x:Int) = if(x==0) 1.0 else 'c'
  println(func(0))
  println(func(1))
}

首先,当我写这篇文章时,我认为Scala不会允许这样的函数,但它将函数解释为1.0 99.0 。这感觉就像是强制类型。

如果我在上面的函数中用(Int) => Double代替'c',它实际上会返回

"c"

其中函数现在被解释为1.0 c

问题:如果Scala是强类型的,为什么第一个带有(Int) => Any的示例返回了一个Double,为什么两个示例中'c'(Int) => Double之间存在差异?

2 个答案:

答案 0 :(得分:6)

Scala中的类型之间存在称为"weak conformance"的关系。 Char弱与Double一致(因为它与Int弱,符合Double)。 if (<cond>) then <e1> else <e2>的类型为defined to be the weak least upper bound (wlub) of types of <e1> and <e2>(对于具有多个分支的其他表达式,存在类似的规则:matchtry/catch)。 CharDouble的wlub是Double; StringDouble的wlub是Any

答案 1 :(得分:1)

Scala会在必要时在类型之间进行隐式转换。通常它通过在范围内的任何位置定义的一些隐式转换来执行此操作(大多数隐式转换都在scala.Predef中,默认情况下是导入的)

为了查看所有可用的隐式转换,请在repl中执行此操作:

:implicits -v

但是,如果这样做,您将看到char2Double没有可用的隐式转换。发生什么了?在这里,scala编译器转向另一种称为numeric widening的转换:

  

如果ee具有与预期类型弱符合的原始数字类型,则使用其中一种数字转换方法将其扩展为预期类型toShort,toChar,toInt,toLong,toFloat,toDouble here here。

所以,正如@Alexey在他的回答中所指出的那样,字符弱于符合双打,字符串&#39; c&#39;通过应用&#39; c&#39;。双倍数字扩展转换,将转换为Double。

此外,您可以禁用Predef中定义的隐式转换,如下所示:

// disable int to Integer conversion
import scala.Predef.{int2Integer => _}

但是,我不确定是否可以禁用数字扩展转换。

正如@ pedrorijo91指出的那样,通过添加合适的scalac标志也可以防止数字扩展:-Ywarn-numeric-widen&amp; -Xfatal-警告