Search code examples
scalamonadsfor-comprehension

How to convert this map/flatMap into a for comprehension in Scala?


How to convert this map/flatMap into a for comprehension, and please explain how it works, thanks.

    def compute2(maybeFoo: Option[Foo]): Option[Int] =
      maybeFoo.flatMap { foo =>
      foo.bar.flatMap { bar =>
          bar.baz.map { baz =>
          baz.compute
      }
    }
  }  

Solution

  • Your code can be translated into this:

    def compute2(maybeFoo: Option[Foo]): Option[Int] =
      for {
        foo <- maybeFoo
        bar <- foo.bar
        baz <- bar.baz
      } yield baz.compute
    

    Quotes from Programming in Scala, Second Edition:

    Generally, a for expression is of the form:

    for ( seq ) yield expr
    

    Here, seq is a sequence of generators, definitions, and filters, with semi-colons between successive elements.

    This for expression contains one generator, one definition, and one filter:

    for {
    p <- persons // a generator
    n = p.name // a definition
    if (n startsWith "To") // a filter
    } yield n
    

    Translating for expressions with one generator

    First, assume you have a simple for expression:

    for (x <- expr1) yield expr2
    

    where x is a variable. Such an expression is translated to:

    expr1.map(x => expr2)
    

    Translating for expressions starting with a generator and a filter

    Now, consider for expressions that combine a leading generator with some other elements. A for expression of the form:

    for (x <- expr1 if expr2) yield expr3
    

    is translated to:

    expr1 withFilter (x => expr2) map (x => expr3)
    

    Translating for expressions starting with two generators

    The next case handles for expressions that start with two generators, as in:

    for (x <- expr1; y <- expr2) yield expr3
    

    The for expression above is translated to an application of flatMap:

    expr1.flatMap(x => for (y <- expr2) yield expr3)