tags:

views:

130

answers:

3

Say I have some scala code like this:

// outputs 1, 4, 9, 16, 25, 36, 49, 64, 81, 100
println( squares )

def squares = {
    val s = for ( count <- 1 to 10 ) yield { count * count }
    s.mkString(", ");
}

Why do I have to use the temporary val s? I tried this:

def squares = for ( count <- 1 to 10 ) yield { count * count }.mkString(", ")

That fails to compile with this error message:

error: value mkString is not a member of Int
   def squares = for ( count <- 1 to 10 ) yield { count * count }.mkString(", ")

Shouldn't mkString be called on the collection returned by the for loop?

+12  A: 

There is a missing parenthesis. You want to call the mkString method on the result of the for-expression. Without the extra parenthesis the compiler thinks you wanted to call the mkString-method on {count * cout} which is an Int.

scala> def squares = (for ( count <- 1 to 10 ) yield { count * count }).mkString(", ")
squares: String

scala> squares
res2: String = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100

Anyway I suggest you to should use the map method instead:

scala> 1 to 10 map { x => x*x } mkString(", ")
res0: String = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100
michael.kebe
His for comprehension is just syntactic sugar for the exact same map method that you provided. What you want to use is just a matter of taste, in my opinion.
Arjan Blokzijl
+4  A: 

Just put parentheses around the for loop and it works:

scala> (for (count <- 1 to 10) yield { count * count }).mkString(", ") 

res0: String = 1, 4, 9, 16, 25, 36, 49, 64, 81, 100

Arjan Blokzijl
+3  A: 

When you call mkString as you have in your second example, it's not being called on the collection but on each individual integer being returned, hence the error message: mkString is not a member of Int.
If you want to call methods on the for..yield expression itself, you'll need to parenthesize it:

def squares = (for (count <- 1 to 10) yield { count * count }).mkString(", ")
tzaman