Как сложить влево список BigDecimal? («перегруженный метод + не может быть применен») - PullRequest
4 голосов
/ 24 сентября 2011

Я хочу написать короткую функциональную сумму для функции List из BigDecimal и попробовал с:

def sum(xs: List[BigDecimal]): BigDecimal = (0 /: xs) (_ + _)

Но я получил это сообщение об ошибке:

<console>:7: error: overloaded method value + with alternatives:
  (x: Int)Int <and>
  (x: Char)Int <and>
  (x: Short)Int <and>
  (x: Byte)Int
 cannot be applied to (BigDecimal)
       def sum(xs: List[BigDecimal]): BigDecimal = (0 /: xs) (_ + _)
                                                                ^

Если вместо этого я использую Int, эта функция работает. Я предполагаю, что это потому, что перегрузка оператора BigDecimal +. Что такое хороший обходной путь для BigDecimal?

Ответы [ 4 ]

16 голосов
/ 24 сентября 2011

Проблема в первоначальной стоимости.Решение здесь и довольно простое:

 sum(xs: List[BigDecimal]): BigDecimal = (BigDecimal(0) /: xs) (_ + _)
2 голосов
/ 24 сентября 2011

В такой ситуации (когда аккумулятор имеет тот же тип, что и элементы в списке), вы можете начать складывание, добавив первый и второй элементы в список, т. Е. Вам не обязательно указывать начальное значение,reduce в Scala обеспечивает такой вид сгиба:

def sum(xs: List[BigDecimal]) = xs.reduce(_ + _)

Существуют также версии reduceLeft и reduceRight, если ваша операция не ассоциативна.

2 голосов
/ 24 сентября 2011

foldLeft требует значения инициализации.

def foldLeft[B](z: B)(f: (B, A) ⇒ B): B

Это значение инициализации (названное z) должно быть того же типа, что и тип для сворачивания:

(BigDecimal(0) /: xs) { (sum: BigDecimal, x: BigDecimal) => sum+x }
// with syntax sugar
(BigDecimal(0) /: xs) { _+_ }

Если вы добавите Int в качестве значения инициализации, foldLeft будет выглядеть так:

(0 /: xs) { (sum: Int, x: BigDecimal) => sum+x } // error: not possible to add a BigDecimal to Int
0 голосов
/ 24 сентября 2011

Как уже говорили другие, вы получили ошибку из-за начального значения, поэтому правильный способ - обернуть ее в BigDecimal.Кроме того, если у вас есть несколько таких функций и вы не хотите писать BigDecimal(value) везде, вы можете создать неявную функцию преобразования следующим образом:

implicit def intToBigDecimal(value: Int) = BigDecimal(value)

, и в следующий раз Scala будет молча конвертировать все ваши Ints(включая константы) в BigDecimal.На самом деле, большинство языков программирования используют тихие преобразования из целых в десятичные или даже из десятичных дробей в дробные (например, Лиспс), так что это кажется очень логичным шагом.

...