2

After reading this excellent answer on for-expressions, I tried to convert my flatMap to a for-expression.

val results: List[String] = foo()
def getId: List[String] = List((json \ "_id").asOpt[String].getOrElse(""))
val xs: List[String] = results.flatMap( x => getId(Json.parse(x)))

Then, the for-expression.

val results: List[String] = foo()
def getId: List[String] = List((json \ "_id").asOpt[String].getOrElse(""))
val xs: List[String] = for { 
    r <- result
    getId(Json.parse(r))
}

I get a compile-time error that <- was expected on the getId(...) line, but found }.

What's wrong with my for expression?

Community
  • 1
  • 1
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

1 Answers1

2

Your for-comprehension needs to bind the result of getId to a name, and yield that:

val xs: List[String] = for {
  r <- result
  x <- getId(Json.parse(r))
} yield x

Each line inside the for-comprehension needs to either bind the result of a monadic computation to a name using

x <- expr

// or, `_ <- expr` to run `expr` purely for its effects and ignore the result

or it needs to be a simple assignment such as

x = expr

Since getId(Json.parse(r)) alone does neither, this is invalid.

Ben James
  • 121,135
  • 26
  • 193
  • 155
  • ah, so `yield` is **always** required? In the case of map to for-expression, yield will return a List[...]. But for a flatMap to for-expression, yield will return a List[List[...]]? – Kevin Meredith Oct 16 '13 at 16:40
  • 1
    `yield` is required if you want to get a value (as opposed to just side-effects.) I'm not sure where you got `List[List[...]]` from. – Ben James Oct 16 '13 at 16:45