Reputation: 166
Complete beginner to Scala and just trying to figure out the basics right now.
As part of a tutorial I'm trying to create a function that returns the largest element in a list of integers. To accomplish this I've (tentatively) put together a the following code:
def max(xs: List[Int]): Int =
if (xs.isEmpty)
throw new java.util.NoSuchElementException
else
findMax(xs.head, xs.tail)
def findMax(a: Int, b: List[Int]) {
if (b.isEmpty) return a
if (a > b.head)
findMax(a, b.tail)
else
findMax(b.head, b.tail)
}
However, when I try to compile it I get a type error for line 5.
[error] /scala/example/src/main/scala/example/Lists.scala:5: type mismatch;
[error] found : Unit
[error] required: Int
[error] findMax(xs.head, xs.tail)
I have to admit I'm a bit confused by this error message as I don't understand how the compiler thinks I'm trying to pass in a Unit type given the logic to ensure a List is not empty prior to this line.
Can anyone help to clarify the issue here?
Upvotes: 1
Views: 1530
Reputation: 1395
Scala has two constructs for defining a function:
def doSomething(a: Int) { a + 3 }
and
def doSomethingElse(b: Int) = { b + 3 }
The first one is known as procedure syntax, and it is discouraged because it leads to poor assumptions and confusing code. The difference between these two functions is that doSomething
returns Unit
, whereas doSomethingElse
returns Int
. If you do not include an =
, your function will not return anything (in other words, it returns Unit
).
This
def doSomething(a: Int) { a + 3 }
is equivalent to
def doSomething(a: Int): Unit = { a + 3 }
You want your function findMax
to return an Int, but because you left off the =
, Scala says it returns Unit
. This is the cause of your compile error. You can fix this by either writing
def findMax(a: Int, b: List[Int]) = {
or
def findMax(a: Int, b: List[Int]): Int = {
In general, you should never use procedure syntax. Always use =
, even if you ultimately leave the final return type up to type inference.
It should be noted that the first approach might actually result in a compiler error because you used return
in your function. Functions that explicitly call return
are required to specify the type that they return in the function header. Because Scala is an expression-based language, every statement is an expression and thus returns a value. You can rewrite your findMax
function to not need return
as follows:
def findMax(a: Int, b: List[Int]): Int = {
if (b.isEmpty)
a
else if (a > b.head)
findMax(a, b.tail)
else
findMax(b.head, b.tail)
}
Upvotes: 7