At a glance a for-comprehension appears to be equivalent to a Java for-loop, but it is much much more than that. As shown in post:
for-comprehensions, for-comprehensions can have guards which filter out which elements are processed:
- scala> for ( x <- 1 to 10; if (x >4) ) println(x)
- 5
- 6
- 7
- 8
- 9
- 10
They can be used to construct new collections:
- scala>?for(?i?<-?List(?"a",?"b",?"c")?)?yield?"Word:?"+i
- res1:?List[java.lang.String]?=?List(Word:?a,?Word:?b,?Word:?c)
They can contain multiple
generators:
- scala> for {x <- 1 to 10
- | if(x%2 == 0)
- | y <- 1 to 5} yield (x,y)
- res1: scala.collection.immutable.IndexedSeq[(Int, Int)] = IndexedSeq((2,1), (2,2), (2,3), (2,4), (2,5), (4,1), (4,2), (4,3), (4,4), (4,5), (6,1), (6,2), (6,3), (6,4), (6,5), (8,1), (8,2), (8,3), (8,4), (8,5), (10,1), (10,2), (10,3), (10,4), (10,5))
What has not been covered is that the assignments also does pattern matching:
- scala> for ( (x,y) <- (6 to 1 by -2).zipWithIndex) println (x,y)
- (6,0)
- (4,1)
- (2,2)
This is not surprising as this also occurs during normal assignment. But what is interesting is that the pattern matching can act as a guard as well. See
Extractor examples and
Assignment and Parameter Objects for more information of pattern matching and extractors.
- scala> val args = Array( "h=2", "b=3")
- args: Array[java.lang.String] = Array(h=2, b=3)
- scala> val Property = """(.+)=(.+)""".r
- Property: scala.util.matching.Regex = (.+)=(.+)
- scala> for {Property(key,value) <- args } yield (key,value)
- res0: Array[(String, String)] = Array((h,2), (b,3))
- scala> Map(res0:_*)
- res1: scala.collection.immutable.Map[String,String] = Map(h -> 2, b -> 3)
- scala> res1("h")
- res3: String = 2
Now just for fun here is a similar example but using symbols instead of strings for the key values:
- scala> val args = Array( "h=2", "b=3")
- args: Array[java.lang.String] = Array(h=2, b=3)
- scala> val Property = """(.+)=(.+)""".r
- Property: scala.util.matching.Regex = (.+)=(.+)
- scala> for {Property(key,value) <- args } yield (Symbol(key),value)
- res0: Array[(Symbol, String)] = Array(('h,2), ('b,3))
- scala> Map(res0:_*)
- res1: scala.collection.immutable.Map[Symbol,String] = Map('h -> 2, 'b -> 3)
- scala> res1('h)
- res2: String = 2