Why is my Scala function returning type Unit and not whatever is the last line?

Go To StackoverFlow.com


I am trying to figure out the issue, and tried different styles that I have read on Scala, but none of them work. My code is:


val str = "(and x y)";

def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int )  

    var b = pos; //position of where in the expression String I am currently in
    val temp = expreshHolder; //holder of expressions without parens
    var arrayCounter = follow; //just counts to make sure an empty spot in the array is there to put in the strings

    if(exp(b) == '(') {
        b = b + 1;

        while(exp(b) == ' '){b = b + 1} //point of this is to just skip any spaces between paren and start of expression type

        if(exp(b) == 'a') {
               temp(arrayCounter) = exp(b).toString; 
               b = b+1; 
               temp(arrayCounter)+exp(b).toString; b = b+1; 
               temp(arrayCounter) + exp(b).toString; arrayCounter+=1}



val hold: ArrayBuffer[String] = stringParse(str, 0, new ArrayBuffer[String], 0);
for(test <- hold) println(test);

My error is:

Driver.scala:35: error: type mismatch;
found   : Unit
 required: scala.collection.mutable.ArrayBuffer[String]
ho = stringParse(str, 0, ho, 0);
                ^one error found

When I add an equals sign after the arguments in the method declaration, like so:

def stringParse ( exp: String, pos: Int, expreshHolder: ArrayBuffer[String], follow: Int )  ={....}

It changes it to "Any". I am confused on how this works. Any ideas? Much appreciated.

2012-04-04 05:19
by Andy
+1 for something a newb will always face. The explanation is also a little counter-intutive too - Jesvin Jose 2012-04-04 06:41


You have to add the equals sign if you want to return a value. Now, the reason that your function's return value is Any is that you have 2 control paths, each returning a value of a different type - 1 is when the if's condition is met (and the return value will be temp) and the other is when if's condition isn't (and the return value will be b=b+1, or b after it's incremented).

2012-04-04 05:24
by Tal Pressman
Why would the return value be b=b+1 if the if is not met? But I see what you mean. In java it is not like that, so its weird to think that scala includes the other cases - Andy 2012-04-04 05:31
Never mind about the why b=b+1. That makes sense. I formatted it differently on here, so when I looked at it in my editor it made sense. Thanks for pointing me in the right direction - Andy 2012-04-04 05:33
First, you have to decide what value you want returned from the function in case the if's condition isn't met. Then you can either "use" that value before the if or add an else clause and put it there - Tal Pressman 2012-04-04 05:41
Yes, thank you. I tried it, but now I am getting other errors, not related to my question so now on to research on why that is. I really appreciate it - Andy 2012-04-04 05:43


Here's a more general answer on how one may approach such problems:

It happens sometimes that you write a function and in your head assume it returns type X, but somewhere down the road the compiler disagrees. This almost always happens when the function has just been written, so while the compiler doesn't give you the actual source (it points to the line where your function is called instead) you normally know that your function's return type is the problem.

If you do not see the type problem straight away, there is the simple trick to explicitly type your function. For example, if you thought your function should have returned Int, but somehow the compiler says it found a Unit, it helps to add : Int to your function. This way, you help the compiler to help you, as it will spot the exact place, where a path in your function returns a non-Int value, which is the actual problem you were looking for in the first place.

2012-04-04 05:51
by Frank
Thank you. Yes, I tried that, but it still gave me the error. I assumed that might have been a problem, but it did not solve it, at least for my problem. In terms of other situations that would have definitely helped. I am new to the language and I appreciate the input - Andy 2012-04-04 20:18


class Test(condition: Boolean) {

  def mixed = condition match {
    case true  => "Hi"
    case false => 100

  def same = condition match {
    case true  => List(1,2,3)
    case false => List(4,5,6)

  case class Foo(x: Int)
  case class Bar(x: Int)

  def parent = condition match {
    case true  => Foo(1)
    case false => Bar(1)
val test = new Test(true)

test.mixed   // type: Any
test.same    // type List[Int]
test.parent  // type is Product, the case class super type

The compiler will do its best to apply the most specific type it can based on the possible set of result types returned from the conditional (match, if/else, fold, etc.).

2012-04-04 08:34
by virtualeyes