Copia de mi respuesta de la lista de correo Scala, donde la cuestión era primero preguntó:
Number
es una clase Java, y no tiene ninguna funcionalidad aparte de la conversión en sí a los tipos primitivos. Desafortunadamente, el AnyVal
de Scala no hace nada aparte de marcar los tipos primitivos, y Numeric[T]
de Scala solo conoce su propio tipo, no una combinación de tipos.
Así que te queda una coincidencia de patrones bastante desagradable; la sintaxis más corta si está seguro es suficiente para manejar doble y int es:
list.reduceLeft((l,r) => (l: Any, r: Any) match {
case (li: Int, ri: Int) => li + ri
case _ => l.doubleValue + r.doubleValue
})
Nota que estoy echando a Any
para obtener el ajuste de patrones Scala para hacer el unboxing para nosotros; si lo dejas como Número, debes hacer coincidir el patrón en java.lang.Integer
y luego en valueOf
, lo cual es un problema.
Si quieres más se va a tener que construir en las promociones apropiadas:
list.reduceLeft((l,r) => (l: Any) match {
case li: Int => (r: Any) match {
case ri: Int => li + ri
case rf: Float => li + rf
case rl: Long => li + rl
case _ => li + r.doubleValue
}
case lf: Float => /* etc. */
})
Si usted tiene que hacer esto más que un poco, usted es probablemente mejor de abandonar Numeric
a favor de su propio clases de envoltura que saben cómo sumarse con la promoción adecuada; luego puede escribir la coincidencia de patrón una sola vez y volver a usar + en su lista de comprensiones.
sealed abstract class Addable {
def +(a: Addable): Addable
}
final case class MyInt(value: Int) extends Addable {
def +(a: Addable) = a match {
case MyInt(i) => MyInt(value + i)
case MyFloat(f) => MyFloat(value + f)
...
}
}
final case class MyFloat(value: Float) extends Addable {
def +(a: Addable) = a match {
case MyInt(i) => MyFloat(value + i)
...
}
}
...
Una ligera ventaja de este método es que se puede decidir para promover los valores de una manera diferente a la norma (por ejemplo, puede decidir que flotan + tiempo = doble, desde un flotador en realidad no se corta . para mantener la mayor parte de la precisión numérica del tiempo, y hacer MyDouble(value.toDouble + f.toDouble)
, por ejemplo
todo es bastante incómodo, ni Java ni Scala realmente proporcionan apoyo a las matemáticas de tipo mixto
para referencia futura, se considera mejor forma de preguntar. una pregunta _either_ en la lista de correo de Scala _o_ StackOverflow, no ambas. Para preguntas como esta en particular lar, StackOverflow suele ser la mejor opción, ya que es más fácil para otros aprender de la pregunta y la respuesta aquí que en los archivos de la lista de correo. –
Estoy parado. Eso no volverá a pasar. Gracias por toda la ayuda y por ser tan gentil en enseñarme netiqueta. – Andres