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
的便利性