Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala for ( ) vs for { }

Tags:

scala

I'm trying to understand for comprehensions in Scala, and I have a lot of examples that I sort of understand...

One thing I'm having a hard time figuring out is for ( ) vs for { }. I've tried both, and it seems like I can do one thing in one but it breaks in the other.

For example, this does NOT work:

def encode(number: String): Set[List[String]] =
  if (number.isEmpty) Set(List())
  else {
    for (
      split <- 1 to number.length
      word <- wordsForNum(number take split)
      rest <- encode(number drop split)
    ) yield word :: rest
  }.toSet

However, if you change it to { }, it does compile:

def encode(number: String): Set[List[String]] =
  if (number.isEmpty) Set(List())
  else {
    for {
      split <- 1 to number.length
      word <- wordsForNum(number take split)
      rest <- encode(number drop split)
    } yield word :: rest
  }.toSet                                 

These examples are from a Coursera class I'm taking. The professor didn't mention the "why" in the video & I was wondering if anyone else knows.

Thanks!

like image 794
anonygrits Avatar asked Nov 01 '14 04:11

anonygrits


1 Answers

From the syntax in the spec, it might seem that parens and braces are interchangeable:

http://www.scala-lang.org/files/archive/spec/2.11/06-expressions.html#for-comprehensions-and-for-loops

but because the generators are separated by semis, the following rules kick in:

http://www.scala-lang.org/files/archive/spec/2.11/01-lexical-syntax.html#newline-characters

I have read and understood that section in the past, from which I vaguely recall the gist that newlines are enabled in the braces, which is to say, a newline char is taken as nl which serves as a semi.

So you can put the generators on separate lines instead of using semicolons.

This is the usual "semicolon inference" that lets you not write semicolons as statement terminators. So the newline in the middle of the generator is not taken as a semi, for instance:

scala> for (c <-
     | List(1,2,3)
     | ) yield c+1
res0: List[Int] = List(2, 3, 4)

scala> for { c <-
     | List(1,2,3)
     | i = c+1
     | } yield i
res1: List[Int] = List(2, 3, 4)
like image 113
som-snytt Avatar answered Oct 29 '22 00:10

som-snytt