Добавление чисел вместе - PullRequest
6 голосов
/ 18 июня 2011

У меня есть список [номер]. Он содержит значения различных подклассов Number - Int, Double и так далее. Я хочу суммировать все значения вместе. Если список содержит только Int, я бы хотел, чтобы результат был Int. Если есть миксы, я бы хотел следовать обычным правилам Scala: Int + Double = Double (и т. Д.).

Я пробовал это:

val result = list.reduceLeft(_ + _)

Это даже не компилируется. Для Number не определен метод +, который принимает другой номер.

Как мне это сделать?

1010 * Андрес *

Ответы [ 2 ]

9 голосов
/ 18 июня 2011

Копирование моего ответа из списка рассылки Scala, где впервые был задан вопрос:

Number является классом Java и не имеет никакой функциональности, кроме преобразования себя в примитивные типы.К сожалению, AnyVal в Scala не делает ничего, кроме маркировки примитивных типов, а Numeric[T] из Scala знает только о своем собственном типе, а не о сочетании типов.

Таким образом, у вас остается довольнонеприятное сопоставление с образцом;самый короткий синтаксис, если вы уверены, что вам нужно обрабатывать только double и int, это:

list.reduceLeft((l,r) => (l: Any, r: Any) match {
  case (li: Int, ri: Int) => li + ri
  case _ => l.doubleValue + r.doubleValue
})

Обратите внимание, что я использую Any, чтобы получить совпадение с шаблоном Scala для распаковки;если вы оставите его как Number, вам придется сопоставить шаблон с java.lang.Integer, а затем valueOf it, что является болью.

Если вы хотите больше, вам нужно будет встроить соответствующие акции:

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. */
})

Если вам нужно сделать это немного больше, вам, вероятно, лучше отказаться от Numeric в пользу ваших собственных классов-обёрток, которые знают, как сложить себя вместе с соответствующей рекламой;затем вы можете написать сопоставление с образцом только один раз и вернуться к использованию + в своих списках.

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)
    ...
  }
}

...

Одним небольшим преимуществом этого метода является то, что вы можете решить продвигать значения не так, как стандартные (дляНапример, вы можете решить, что float + long = double, так как float действительно не вырезан, чтобы сохранить большую часть числовой точности long, и, например, выполните MyDouble(value.toDouble + f.toDouble).

Это все довольно неловко;Java или Scala действительно предоставляют поддержку математики смешанного типа.

0 голосов
/ 18 июня 2011

Сокращая список Double с.

Не используйте класс Number, вы ничего не сможете сделать с ним.Это даже не класс Scala, это класс Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...