Reputation: 135
I am trying to solve the Project Euler, Problem 5. I have found many solutions on the Internet but I'm trying my own version (not so functional approach). I am stuck with an error: type mismatch found :Unit Required:Boolean
.
object Euler5 {
def divby1to10(input: Int): Boolean = {
for (i <- 1 to 10) { // type mismatch found :Unit Required:Boolean
if (input % i == 0)
false
else true
}
}
def main(args: Array[String]): Unit = {
println(divby1to10(5))
}
}
If I remove the :Boolean
, the code compiles but the output is ()
. Can someone help me to figure out what is wrong with this code and give me a solution for this?
Upvotes: 0
Views: 1799
Reputation: 967
In Scala, unlike other programming languages e.g. Java control flow constructs like if, for and while are expressions which return value of some type.
In given specific example your for statement returns Unit because of the following statement in Scala language specification which states:
A for loop for (p <- e) e′ is translated to e.foreach { case p => e′ }
In your example e has a type Range (more specifically - Range.Inclusive). For that type foreach is defined so that it returns Unit. As a result your entire for expression produces Unit. Finally as your for expression is the last statement of your function the function itself also returns Unit, hence the error.
Normally foreach constructs instead of returning some values are used to produce side effects on each generated value p, e.g. print something into console hence the return type Unit. So for your specific task probably it doesn't fit well. As were explained in other answers there are several ways to rewrite your logic so that your function returns boolean value.
Upvotes: 0
Reputation: 17433
The problem is that your for
loop has return type Unit
and in your function definition you are requiring Boolean
.
A more functional approach to express your logic could be:
def divby1to10(input: Int): Boolean = (1 to 10).forall(input % _ == 0)
Upvotes: 1
Reputation: 70267
Think about what your for
loop is doing.
for (i <- 1 to 10) {
if (input % i == 0)
false
else true
}
You're looping ten times and producing ten different results. Now, I imagine you want these false
and true
values to propagate outward, but what if some of the iteration steps return false
and others true
? You haven't specified how you want them combined. For this reason, in Scala, an (imperative) for
loop always returns ()
. I think what you want is
for (i <- 1 to 10) {
if (input % i != 0)
return false // Definitely doesn't divide them all, so return false now
// If it does divide, continue the loop
}
// If we get to this point, it divided them all, so return true
true
Upvotes: 2