Start learning free

LESSON 136 OF 414 · LOOPS & CONDITIONALS

Check for Positive Numbers in Scala: Fixing the Buggy Code

Practice Read the full explanation

Inside the code editor we've tried to write a function that takes an array nums as argument and returns true if there exists at least one positive (greater than zero) number in the array; returns false otherwise.

So when we called the function for [-1, 2, 3], we expected our program to print:

Array has positive numbers

but it seems like we made a mistake because our code doesn't even compile. The compiler reports:

Type Mismatch Error
Found:    Unit
Required: Boolean

Assignment:

Your task is to fix our function.

STEP 1 OF 1
    Ctrl + Enter to check

    SCALA · LOOPS & CONDITIONALS

    Buggy Code Check For Positive Numbers in Scala, explained

    What the code is supposed to do

    The method checkForPositive receives an Array[Int] and returns true if at least one number in it is greater than zero, and false if there is none. For [-1, 2, 3] the answer is true, so the program should print Array has positive numbers.

    The code you start with doesn't even compile:

    class Solution {
        def checkForPositive(nums: Array[Int]): Boolean = {
            for (num <- nums) {
                if (num > 0) {
                    return true
                } else {
                    return false
                }
            }
        }
    
        // Do not change this code:
        def mainFunction(): Unit = {
            if (checkForPositive(Array(-1, 2, 3))) {
                println("Array has positive numbers")
            } else {
                println("Array doesn't have positive numbers")
            }
        }
    }
    

    What goes wrong

    There are two problems, and they are connected.

    The loop gives up after one element

    Follow the code for [-1, 2, 3]. The first element is -1. It is not greater than zero, so the else branch runs and the method returns false. A return ends the whole method, so the elements 2 and 3 are never looked at. The method has answered "no positive numbers" after seeing a single negative number, which says nothing about the rest of the array.

    Whenever the first element is positive, the method returns true and is right, and whenever it isn't, the method returns false and may be wrong. In effect it only checks the first element.

    The method can finish without a result

    Scala also rejects the code at compile time. The compiler reports a type mismatch like this:

    Type Mismatch Error
            for (num <- nums) {
            ^
            Found:    Unit
            Required: Boolean
    

    A Scala method's result is its last expression, and here the last expression is the for loop. A for loop without yield produces Unit, not a Boolean. Every path through the loop body happens to return, but the compiler doesn't reason that way: a loop over an empty array runs zero times and then the method ends with the loop's Unit value. That is why it insists on a Boolean there.

    Both problems have one cause. A single "no" must not end the search, because only the end of the loop proves that every number failed.

    Fixing it step by step

    1. Remove the else branch. A number that isn't positive needs no action. The loop just moves on to the next one.
    2. Keep return true in the if. One positive number is enough to answer true straight away.
    3. Add return false after the loop. It runs only when the loop has looked at every element and none was positive. It also gives the method a Boolean as its last expression, so the type mismatch disappears. An empty array reaches it directly and gets false.

    The fixed code in Scala

    class Solution {
        def checkForPositive(nums: Array[Int]): Boolean = {
            for (num <- nums) {
                if (num > 0) {
                    return true
                }
            }
            return false
        }
    
        def mainFunction(): Unit = {
            if (checkForPositive(Array(-1, 2, 3))) {
                println("Array has positive numbers")
            } else {
                println("Array doesn't have positive numbers")
            }
        }
    }
    

    For [-1, 2, 3] the loop skips -1, meets 2, returns true, and the program prints Array has positive numbers. For [-1, -2] and for an empty array the method returns false.

    Some Scala details behind the fix:

    • The last expression is the value. That is why a Boolean method can't end with a bare for loop. Ending with false would work as well as return false.
    • Warnings are not errors. Scala 3.5 compiles the fixed code with a warning that a return inside a for body is a non-local return, which is deprecated. The code still runs and prints the expected line.
    • Zero is not positive. The test is num > 0, strictly greater. An array such as [0, -3] gives false.
    • A shorter way exists. nums.exists(_ > 0) returns the same answer without a loop. The lesson uses the explicit loop to practise the pattern.

    Tracing the fixed method

    Following the values through the loop shows why the order of the checks matters.

    • [-1, 2, 3]. The first pass has num = -1, the condition is false and the loop continues. The second pass has num = 2, the condition is true and the method returns true. The element 3 is never visited, because the answer is already known.
    • [-4, 0, -7]. All three passes find a condition that is false. The loop ends, and the line after it returns false.
    • []. There are no passes. The method goes straight to return false, which is correct because an empty array holds no positive number.

    The shape is the same as any "does at least one element satisfy a condition" search: a positive answer can come from the middle of the loop, while a negative answer can only come after the loop, once every element has been checked. Searching for a value, or for an element with some property, follows the same pattern.

    Common mistakes

    • Returning false inside the loop. Any return false in the loop body ends the search early, even if it sits in a different branch.
    • Fixing only the compile error. Adding false after the loop but keeping the else branch makes the code compile, but it still prints "doesn't have positive numbers" for [-1, 2, 3].
    • Using >=. That would count zero as positive.
    • Editing mainFunction. It is marked as code not to change.

    Checking your fix

    Run the code in the editor above. It should compile and print Array has positive numbers. If you still see the type mismatch, the method can still reach its end without a Boolean.

    Keep going with ScalaAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free