5

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?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
1984isnotamanual
  • 595
  • 1
  • 4
  • 7

3 Answers3

18

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
  • 10,916
  • 3
  • 44
  • 62
  • 2
    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 Jun 02 '10 at 14:42
6

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
  • 6,878
  • 2
  • 31
  • 27
3

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
  • 46,925
  • 11
  • 90
  • 115