以下代码
;; 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
之间存在差异?
答案 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>
(对于具有多个分支的其他表达式,存在类似的规则:match
和try/catch
)。 Char
和Double
的wlub是Double
; String
和Double
的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-警告