tags:

views:

212

answers:

2

Here is the POC code:

object TypeTest extends Application {
    val stuff = List(1,2,3,4,5)
    def joined:String = stuff.reduceLeft(_ + ", " + _)

    println(joined)
}

Upon compiling, it gives the following error:

tt.scala:4: error: type mismatch;
 found   : java.lang.String
 required: Int
    def joined:String = stuff.reduceLeft(_ + ", " + _)
                                                      ^
tt.scala:4: error: type mismatch;
 found   : Int
 required: String
    def joined:String = stuff.reduceLeft(_ + ", " + _)
                                  ^

Writing the joined function like

reduceLeft(_.toString + ", " + _.toString)

does not help, still gives the same error. However, if I write it like

def joined:String = stuff.map(_.toString).reduceLeft(_ + ", " + _)

everything is fine.

Can someone please explain this weird combination of type errors? What is really going on here? The second one is especially weird, since there is an implicit conversion for Int to String.

+1  A: 

I've just start using Scala too. This is what I understand.

'stuff' is a list of Int so 'reduceLeft' requires an Int parameter and returns an Int (base on this). But you put string as a parameter (Error 1) and try to assign the result to string (Error 2). That's why you got such errors.

NawaMan
Thanks. I got it now. That was pretty stupid of me :)
maksymko
+6  A: 

reduceLeft requires the function block (inside the parentheses) to return the same type as the collection. This is because block is invoked recursively until all values of the collection are consumed.

stuff is a List[Int], but (_ +", " + _) is a String, hence the type error.

A similar method to reduceLeft is foldLeft. The distinction is that the collection type and the resultant type can be different. For example:

stuff.foldLeft("") { _ + ", " + _ } // => java.lang.String = , 1, 2, 3, 4

I guess your example is indicative, but if you really want a String of comma separated values, then the following would be better:

stuff.mkString(", ") // => String = 1, 2, 3, 4
Synesso
Ah, yeah, you right. I somehow confused it with the fold*
maksymko