I have a method that is supposed to return an Int. I am trying to understand why Eclipse won’t let me compile this, even though it looks apparent to me inside the if statement that I am indeed returning an Int. Is there something I am missing very obvious? I am trying to understand this aspect of Scala before proceeding to write more code.
Here is the method:
def contains1(sfType: TokenType): Int = {
if (Tokens.KEYWORDS.contains(sfType)) {
val retVal = TokenTypes.RESERVED_WORD
}
}
Eclipse complains on line 2 — ‘type mismatch; found : Unit required: Int”
TokenTypes is - public abstract interface org.fife.ui.rsyntaxtextarea.TokenTypes and RESERVED_WORD is - public static final int RESERVED_WORD = 6;
I have read this post here: found: Unit required: Int – How to correct this? and tried to solve the problem before posting it, but I am still at a loss.
Edit: The method is supposed to return an Int and I had typed in the return type wrongly. My problem remains the same. Eclipse still complains.
I’ll first explain what type
Unitis, just in case. Even if you know already, other people having the same kind of problem might well not know it.Type
Unitis similar to what is known in C or Java asvoid. In those languages, that means “this does not return anything”. However, every method in Scala returns a value.To bridge the gap between every method returning something and not having anything useful to return, there’s
Unit. This type is anAnyVal, which means it isn’t allocated on the heap, unless it gets boxed or is the type of a field on an object. Furthermore, it has only one value, whose literal is(). That is, you could write this:The practical effect of this is that, when a method “returns”
Unit, the compiler doesn’t have to actually return any value, since it already knows what that value is. Therefore, it can implement methods returningUnitby declaring them, on the bytecode level, as beingvoid.Anyway, if you don’t want to return anything, you return
Unit.Now let’s look at the code given. Eclipse says it returns
Unit, and, in fact, Eclipse is correct. However, most people would actually make the error of having that method returnAnyValorAny, notUnit. See the following snippet for an example:So, what happened? Well, when Scala finds an
ifstatement, it has to figure out what is the type returned by it (in Scala,ifstatements return values as well). Consider the following hypothetical line:Clearly, the returned value will be either
xory, so the type must be such that bothxandywill fit. One such type isAny, since everything has typeAny. If bothxandywere of the same type — say,Int— then that would also be a valid return type. Since Scala picks the most specific type, it would pickIntoverAny.Now, what happens when you don’t have an
elsestatement? Even in the absence of anelsestatement, the condition may be false — otherwise, there would be no point in usingif. What Scala does, in this case, is to add anelsestatement. That is, it rewrites thatifstatement like this:Like I said before: if you do not have anything to return, return
Unit! That is exactly what happens. Since bothIntandUnitareAnyVal, and given thatAnyValis more specific thanAny, that line returnsAnyVal.So far I have explained what others might have seen, but not what happens in that specific code in the question:
We have seen already that Scala will rewrite it like this:
We have also seen that Scala will pick the most specific type between the two possible results. Finally, Eclipse tells use that the return type is
Unit, so the only possible explanation is that the type of this:is also
Unit. And that’s precisely correct: statements that declare things in Scala have typeUnit. And, so, by the way, do assignments.The solution, as others have pointed out, is to remove the assignment and add an
elsestatement also returning anInt:(note: I have reformatted the method to follow the coding style more common among Scala programmers)