Scala-如何更改编译器行为(自动转换为浮点类型)?
例如,这段代码编译并输出Scala-如何更改编译器行为(自动转换为浮点类型)?,scala,floating-point,type-conversion,implicit-conversion,Scala,Floating Point,Type Conversion,Implicit Conversion,例如,这段代码编译并输出false,因为Scala编译器隐式地将Ints转换为Doubles,而不是创建List[AnyVal],这对我来说很奇怪,因为这会导致数据丢失(例如,浮点类型并不精确;它可以对其他可能有危险的隐式转换的类型执行类似的操作。)为什么Scala的设计者选择这样做?(我使用的是版本2.9) 列表的类型是一致的。当您将不同类型的项放入列表时,编译器必须确定整个列表的类型。当您将Double和Int放入列表时,Scala决定列表的类型应为列表[Double]因为这两个项目都可以转
false
,因为Scala编译器隐式地将Int
s转换为Double
s,而不是创建List[AnyVal]
,这对我来说很奇怪,因为这会导致数据丢失(例如,浮点类型并不精确;它可以对其他可能有危险的隐式转换的类型执行类似的操作。)为什么Scala的设计者选择这样做?(我使用的是版本2.9)
列表
的类型是一致的。当您将不同类型的项放入列表
时,编译器必须确定整个列表的类型。当您将Double和Int放入列表
时,Scala决定列表
的类型应为列表[Double]
因为这两个项目都可以转换为。请参见REPL中的:
scala> val y = List(3, 2.0)
y: List[Double] = List(3.0, 2.0)
修复方法是手动将列表转换为列表[Int]
:
scala> val y = List(3, 2.0).map(_.toInt)
y: List[Int] = List(3, 2)
这样,您的测试结果为true
:
scala> println(x.head / 2 == y.head / 2)
true
列表
的类型是一致的。当您将不同类型的项放入列表
时,编译器必须确定整个列表的类型。当您将Double和Int放入列表
时,Scala决定列表
的类型应为列表[Double]
因为这两个项目都可以转换为。请参见REPL中的:
scala> val y = List(3, 2.0)
y: List[Double] = List(3.0, 2.0)
修复方法是手动将列表转换为列表[Int]
:
scala> val y = List(3, 2.0).map(_.toInt)
y: List[Int] = List(3, 2)
这样,您的测试结果为true
:
scala> println(x.head / 2 == y.head / 2)
true
这里只有两种可能:升级到
Double
或加宽到AnyVal
。在后一种情况下,甚至没有定义除法,这有点无用。如果需要此行为,可以显式指定类型:
val y = List[AnyVal](3,2.0)
y.head match {
case i: Int => println("Whew, it is still an int!") // This is printed
case _ => println("Bah, it messed up again")
}
这里只有两种可能:升级到
Double
或加宽到AnyVal
。在后一种情况下,甚至没有定义除法,这有点无用。如果需要此行为,可以显式指定类型:
val y = List[AnyVal](3,2.0)
y.head match {
case i: Int => println("Whew, it is still an int!") // This is printed
case _ => println("Bah, it messed up again")
}
如果你不想转换成浮点数类型,那为什么要创建包含浮点数的列表?如果你不想,就不要在列表中插入任何浮点数或将这些浮点数转换成非浮点数。如果你不想转换成浮点数类型,那为什么要创建g有浮点数的列表?如果您不想这样做,请不要在其中插入任何浮点数或将这些浮点数转换为非浮点数。是的,我知道。但对于其他混合列表,编译器会自动选择AnyVal或最低公共层次父级。(例如:val x=List(List(1),Vector(1))//x:List[Seq[Int]]因为List[T]是Seq[T]而Vector[T]是Seq[T]对于所有T)数字类型的行为在我看来都是例外,因为Double不是Int的超类型,因为(显然)Int不能保存大多数有效的双精度值。相反,在某些情况下,这种转换可能会导致数据丢失,我很惊讶编译器甚至没有给出警告。@SargeBorsch-考虑到Java将Int提升为双精度值,并且Scala借用了相同的策略(大概是为了帮助采用,并遵守Java用户最少惊讶的原则),在问“嘿,我可以扩大到AnyVal吗?”之前先问“嘿,我可以升级到两倍吗?”是有道理的。否则,当你预期升级时,你会得到奇怪的惊喜(例如
math.max(3,2.0)
和List(3,2.0).max
)。可能是。但这很遗憾。我选择Scala主要是因为它与Java不同,能够为Android编写程序,而不使用Java,因为Java的设计失败。似乎它是目前唯一99%兼容的工作选择。@SargeBorsch-如果有关闭它的选项,那就太好了。不过,对于90%的使用,我会选择它e方便,不需要在“显然”应该比偶尔发生类型错误的可能性高出一倍的位置上抛出额外的.0
或d
。与Java没有任何区别;该策略并非没有理由。(无论如何,在我关闭3+3.0
-意味着升级到双精度之前,我会先关闭+
-意味着字符串concat方式。)编译时的类型检查错误比运行时错误甚至错误的结果要好,不是吗?是的,我知道。但对于其他混合列表,编译器会自动选择AnyVal,或最低公共层次结构父级。(例如:val x=List(List(1),Vector(1))//x:List[Seq[Int]]因为List[T]是Seq[T],Vector[T]是Seq[T]对于所有T)数字类型的行为在我看来似乎是规则的例外,因为Double不是Int的超类型,因为(显然)Int不能保存大多数有效的双精度值。相反,在某些情况下,这种转换可能会导致数据丢失,我很惊讶编译器甚至没有给出警告。@SargeBorsch-考虑到Java将Int提升为双精度值,并且Scala借用了相同的策略(大概是为了帮助采用,并遵守Java用户最少惊讶的原则),在问“嘿,我可以扩大到AnyVal吗?”之前先问“嘿,我可以升级到两倍吗?”是有道理的。否则,当你预期升级时,你会得到奇怪的惊喜(例如math.max(3,2.0)
和List(3,2.0).max
)。可能是。但这很遗憾。我选择Scala主要是因为它与Java不同,能够为Android编写程序,而不使用Java,因为Java的设计失败。似乎它是目前唯一99%兼容的工作选择。@SargeBorsch-如果有关闭它的选项,那就太好了。不过,对于90%的使用,我会选择它e不需要在“ob”位置上抛出额外的.0
或d
的便利性