‘for’ Expressions

Where a for loop is used for side effects, a for expression is used to transform data. It truly is an expression, and yields a result. While the syntax is similar, the purpose is quite different.

Notes:

  • A for expression can be the body of a method.

Examples:

[1]
val xs = List(1, 2, 3)
val ys = for x <- xs yield x * 2     // ys: List(2, 4, 6)

[2] multiline
val ys =
    for
        // comment
        x <- xs
    yield
        // another comment
        x * 2

The basic non-filtering example is like the map method

[3] basic for-expr is the same as map
val ys = for x <- xs yield x * 2
val ys = xs.map(_ * 2)

[4] yield whatever you need for your algorithm
val names = List("bert", "ernie", "grover")
val nameLengths = for name <- names yield name.length
val nameLengths = for name <- names yield (name, name.length)

Generators, definitions, and guards:

case class Person(firstName: String, lastName: String)

val people = List(
    Person("betty", "rubble"),
    Person("barney", "rubble"),
    Person("wilma", "flintstone"),
    Person("fred", "flintstone")
)

// generator
val rez = for
    p <- people                 // generator
yield
    s"${p.capitalize}"

val rez = for
    p     <- people             // generator
    fname =  p.firstName        // definition
yield
    s"${fname.capitalize}"

val rez = for
    p     <- people             // generator
    fname =  p.firstName        // definition
    if fname.startsWith("b")    // guard
yield
    s"${fname.capitalize}"

Examples of using a for expression as the body of a function:

def onlyScalaFiles(files: Seq[File]): Seq[File] =
    for
        file <- files
        if file.getName.endsWith(".scala")
    yield
        file

def getQueryAsSeq(query: String): Seq[MiniTweet] =
    val queryResults = getTwitterInstance.search(Query(query))
    val tweets = queryResults.getTweets
    for
        status <- tweets
    yield
        ListTweet(
            status.getUser,
            status.getText,
            status.getCreatedAt
        )