StandForTheRight
StandForTheRight

Reputation: 135

Type mismatch error in Scala code

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

Answers (3)

igorpcholkin
igorpcholkin

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

Sebastian
Sebastian

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

Silvio Mayolo
Silvio Mayolo

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

Related Questions