views:

207

answers:

4

Here's a bit of Scala code to sum the values from 1 to 9 which are divisible by 3 or 5. Why does line 5 return a Unit and not a Boolean type?

object Sample {

    def main(args : Array[String]) {
        val answer = (1 until 10).foldLeft(0) ((result, current) => {
            if ((current % 3 == 0) || (current % 5 == 0)) {
                result + current
            }
        })

        println(answer)
    }

}
+11  A: 

The if expression has a type of Unit because there is no else clause. Thus sometimes it returns nothing (Unit) so the entire expression has type Unit.

(I assume you meant to ask why it didn't return Int, not Boolean)

Ben Jackson
You're correct. I didn't realize what was actually going on - I'm really new to functional programming. What's the best way to handle this? Adding an else with result + 0?
Mike
move the `result +` portion out of the `if` block (there's no need to repeat it), and make it `result + if (...) current else 0`
pelotom
Thanks a bunch. :)
Mike
+8  A: 

Here is my solution:

scala> val answer = (1 until 10) filter( current => (current % 3 == 0) || (current % 5 == 0)) sum
answer: Int = 23

Notice the filter instead of if's.

Another one in a even more idiomatic Scala:

( for( x <- 1 until 10 if x % 3 == 0 || x % 5 == 0 ) yield x ) sum
pedrofurla
+1 Another great answer. Thanks for helping me learn a few different ways.
Mike
+8  A: 

Can we ever be too idiomatic? YES WE CAN!

Set(3,5).map(k => Set(0 until n by k:_*)).flatten.sum

[Edit]

Daniel's suggestion looks better:

Set(3,5).flatMap(k => 0 until n by k).sum
Landei
Wouldn't it be better to just use `flatMap`?
Daniel
In fact, if you do so, you can even shorten it to `Set(3,5).flatMap(k => 0 until n by k).sum`.
Daniel
Nice one. Very... err.. arithmetic :)
pedrofurla
+4  A: 

The closest working code to what you did is this:

object Euler {
    def main(args : Array[String]) {
        val answer = (1 until 10).foldLeft(0) ((result, current) =>
            if ((current % 3 == 0) || (current % 5 == 0))
                result + current
            else
                result
        )

        println(answer)
    }
}
Daniel