Scala for/yield examples (‘for’ loop and yield examples)

I just found some notes from when I first began working with Scala, and I was working with the yield keyword in for loops. If you haven't worked with something like yield before, it will be helpful to know how it works. Here's a statement of how the yield keyword works in for loops, based on the documentation in the book, Programming in Scala:

For each iteration of your for loop, yield generates a value which will be remembered. It's like the for loop has a buffer you can’t see, and for each iteration of your for loop another item is added to that buffer. When your for loop finishes running, it will return this collection of all the yielded values. The type of the collection that is returned is the same type that you were iterating over, so a Map yields a Map, a List yields a List, and so on.

Also, note that the initial collection is not changed; the for/yield construct creates a new collection according to the algorithm you specify.

Back to top

Basic for-loop examples

Given that background information, let's take a look at a few for/yield examples. First, let's just yield a collection that is identical to the collection we are looping over:

scala> for (i <- 1 to 5) yield i
res10: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 2, 3, 4, 5)

Nothing too exciting there, but it's a start. Next, let's double every element in our initial collection:

scala> for (i <- 1 to 5) yield i * 2
res11: scala.collection.immutable.IndexedSeq[Int] = Vector(2, 4, 6, 8, 10)

Here's what the modulus operator does in a for/yield loop:

scala> for (i <- 1 to 5) yield i % 2
res12: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 0, 1, 0, 1)
Back to top

for-loop/yield examples over a Scala Array

I mentioned in my description that the for loop yield construct returns a collection that is the same as the collection it is given. To demonstrate this, let's look at the same examples with a Scala Array. Note the type of the collection that is yielded, and compare it to the previous examples:

scala> val a = Array(1, 2, 3, 4, 5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> for (e <- a) yield e
res5: Array[Int] = Array(1, 2, 3, 4, 5)

scala> for (e <- a) yield e * 2
res6: Array[Int] = Array(2, 4, 6, 8, 10)

scala> for (e <- a) yield e % 2
res7: Array[Int] = Array(1, 0, 1, 0, 1)

As you can see, in these examples an Array[Int] was yielded, while in the earlier examples an IndexedSeq[Int] was returned.

Back to top

for loop, yield, and guards (for-loop ‘if’ conditions)

If you're familiar with the Scala for comprehension syntax, you know that you can add 'if' statements to your for loop construct. Tests like these are often referred to as "guards", and you can combine them with the yield syntax, as shown here:

scala> val a = Array(1, 2, 3, 4, 5)
a: Array[Int] = Array(1, 2, 3, 4, 5)

scala> for (e <- a if e > 2) yield e
res1: Array[Int] = Array(3, 4, 5)

As you can see, adding the "if e > 2" guard condition limits the Array we return to the three elements shown.

Back to top

A real-world example

I don’t know if this will make sense out of context, but if you’d like to see a real-world use of a for/yield loop, here you go:

def getQueryAsSeq(query: String): Seq[MiniTweet] = {
    val queryResults = getTwitterInstance.search(new Query(query))
    val tweets = queryResults.getTweets  // java.util.List[Status]
    for (status <- tweets) yield ListTweet(status.getUser.toString, status.getText, status.getCreatedAt.toString)
}

This code uses the JavaConversions package to convert the java.util.List[Status] I get back from Twitter4J into a Seq[MiniTweet]. The loop actually returns a Buffer[ListTweet], which is a Seq[ListTweet]. A MiniTweet is just a small version of a Twitter tweet, with the three fields shown.

Back to top

Summary: Scala for-loop and yield examples

If you’re familiar with Scala’s for-loop construct, you know that there’s also much more work that can be performed in the first set of parentheses. You can add if statements and other statements there, such as this example from the book Programming in Scala:

def scalaFiles = 
  for {
    file <- filesHere
    if file.getName.endsWith(".scala")
  } yield file

I'll try to share more complicated examples like this in the future, but for today I wanted to share some simple for/yield examples, something like “An introduction to the Scala yield keyword.”

Scala ‘yield’

As a quick summary of the yield keyword:

  • For each iteration of your for loop, yield generates a value which is remembered by the for loop (behind the scenes, like a buffer).
  • When your for loop finishes running, it returns a collection of all these yielded values.
  • The type of the collection that is returned is the same type that you were iterating over.

I hope these examples have been helpful. As usual, feel free to leave any questions, comments, or cool examples below.

Back to top

Add new comment

The content of this field is kept private and will not be shown publicly.

Anonymous format

  • Allowed HTML tags: <em> <strong> <cite> <code> <ul type> <ol start type> <li> <pre>
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.