I want to write a short functional sum-function for a List of BigDecimal and tried with:
def sum(xs: List[BigDecimal]): BigDecimal = (0 /: xs) (_ + _)
But I got this error message:
<console>:7: error: overloaded method value + with alternatives:
(x: Int)Int <and>
(x: Char)Int &l开发者_开发问答t;and>
(x: Short)Int <and>
(x: Byte)Int
cannot be applied to (BigDecimal)
def sum(xs: List[BigDecimal]): BigDecimal = (0 /: xs) (_ + _)
^
If I use Int instead, that function works. I guess this is because BigDecimal's operator overloading of +
. What is a good workaround for BigDecimal?
The problem is in inital value. The solution is here and is quite simple:
sum(xs: List[BigDecimal]): BigDecimal = (BigDecimal(0) /: xs) (_ + _)
foldLeft requires an initialization value.
def foldLeft[B](z: B)(f: (B, A) ⇒ B): B
This initialization value (named z
) has to be of the same type as the type to fold over:
(BigDecimal(0) /: xs) { (sum: BigDecimal, x: BigDecimal) => sum+x }
// with syntax sugar
(BigDecimal(0) /: xs) { _+_ }
If you add an Int as initialization value the foldLeft will look like:
(0 /: xs) { (sum: Int, x: BigDecimal) => sum+x } // error: not possible to add a BigDecimal to Int
In a situation like this (where the accumulator has the same type as the items in the list) you can start the fold by adding the first and second items in the list—i.e., you don't necessarily need a starting value. Scala's reduce
provides this kind of fold:
def sum(xs: List[BigDecimal]) = xs.reduce(_ + _)
There are also reduceLeft
and reduceRight
versions if your operation isn't associative.
As others have already said, you got an error because of initial value, so correct way is to wrap it in BigDecimal. In addition, if you have number of such functions and don't want to write BigDecimal(value)
everywhere, you can create implicit convert function like this:
implicit def intToBigDecimal(value: Int) = BigDecimal(value)
and next time Scala will silently convert all your Ints (including constants) to BigDecimal. In fact, most programming languages use silent conversions from integers to decimal or even from decimals to fractions (e.g. Lisps), so it seems to be very logical move.
精彩评论