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
- Remove the
elsebranch. A number that isn't positive needs no action. The loop just moves on to the next one. - Keep
return truein theif. One positive number is enough to answertruestraight away. - Add
return falseafter the loop. It runs only when the loop has looked at every element and none was positive. It also gives the method aBooleanas its last expression, so the type mismatch disappears. An empty array reaches it directly and getsfalse.
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
Booleanmethod can't end with a bareforloop. Ending withfalsewould work as well asreturn false. - Warnings are not errors. Scala 3.5 compiles the fixed code with a warning that a
returninside aforbody 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]givesfalse. - 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 hasnum = -1, the condition is false and the loop continues. The second pass hasnum = 2, the condition is true and the method returnstrue. 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 returnsfalse.[]. There are no passes. The method goes straight toreturn 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
falseinside the loop. Anyreturn falsein the loop body ends the search early, even if it sits in a different branch. - Fixing only the compile error. Adding
falseafter the loop but keeping theelsebranch 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.
