For Comprehensions
Viewing old version fa8064640542b6733208ec9c55ec0ac7f58d3b84; View Current
You can read the wikipedia entry on list comprehensions if you like, but what we’re talking about here is the many ways in which Scala allows you to traverse and process a list.
We’ve seen some of this in ScalaFunctions and XmlLiterals, but these deal with more specific means of traversing a list (e.g. to find a specific element or map elements to other elements). These are all specialized versions of the so-called “for-comprehension”, which is a fancy name for a for loop.
Suppose we have a list of U.S. States that have been tagged with their general location in the U.S. (e.g. “east” vs. “midwest” vs. “south”). Now suppose we wish to get a list of all the states that aren’t on the east, exception for Washington, DC, which, for some reason, we don’t consider “east coast”:
The expression state <- states is a generator, which assigns a value from states to the value state in succession. Each time this happens, the “guard condition” that starts with if is evaluated. If it evaluates to true (or if there is no guard condition), the body of the for-comprehension is evaluated (this is the part that comes after the final paren). In this case, we use the yield keyword, which essentially means “yield this value back to the list we are creating”. Yes, we are creating a list, here. The end result of this is a list of states that matched our guard condition.
If we didn’t want to actually yield a list, we can omit the yield keyword alltogether:
for( state <- states if state.location != 'east || state.code == "DC") println(state)
Nested Loops
Instead of nesting for loops, we can simply add expressions to the comprehension. Suppose we wish to find pairs of states that could be “sister” states; states that aren’t in the same geographic area.
val possibleSisters = for( state1 <- states;
state2 <- states
if state1.location != state2.location)
yield (state1,state2)
Here, we loop through each pair of states, yield a tuple of states that don’t have the same location (a tuple is pretty much what it sounds like, and is created in Scala via parens and commas, as we have done here in the yield clause).
What about map, filter, etc.?
In reality, the for comprehensions are translated by the compiler into calls to map, filter, and flatMap. Section 10.3 of Scala By Example details this.
It is up to you if the for syntax is more readable and more useful than simply using map and filter.
Last Updated 07/25/2009 at 03:15:37 PM by davec
blog comments powered by Disqus
All Content by David Copeland is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.