Scala之旅 7 序列解析(Sequence Comprehension)

Scala提供一个轻量级的符号表达序列解析。可以通过下面的程序来理解序列解析:

object ComprehensionTest1 extends Application {
  def even(from: Int, to: Int): List[Int] =
    for (i <- List.range(from, to) if i % 2 == 0) yield i
  Console.println(even(0, 20))
}


even中的for循环内引入了一个类型为Int的变量i,它在紧随其后的List(from, from + 1, ..., to - 1)范围之内。如果满足i % 2 == 0这个过滤器,就产生这个值。最后程序产生一个属于List中元素的偶数序列。

输出结果为:

List(0, 2, 4, 6, 8, 10, 12, 14, 16, 18)

List.range的实现如下:

def range(start: Int, end: Int): CC[Int] = range(start, end, 1)

  /** Produces a $coll containing equally spaced values in some integer interval.
   *  @param start the start value of the $coll
   *  @param end   the end value of the $coll (the first value NOT contained)
   *  @param step  the difference between successive elements of the $coll (must be positive or negative)
   *  @return       a $coll with values `start, start + step, ...` up to, but excluding `end`
   */
  def range(start: Int, end: Int, step: Int): CC[Int] = {
    if (step == 0) throw new IllegalArgumentException("zero step")
    val b = newBuilder[Int]
    b.sizeHint(Range.count(start, end, step, false))
    var i = start
    while (if (step < 0) end < i else i < end) {
      b += i
      i += step
    }
    b.result
  }


下面是一个稍微复杂一点的示例,它计算0到n-1中,和为v的数对:

object ComprehensionTest2 extends Application {
  def foo(n: Int, v: Int) =
    for (i <- 0 until n;
         j <- i + 1 until n if i + j == v) yield
      Pair(i, j);
  foo(20, 32) foreach {
    case (i, j) =>
      println("(" + i + ", " + j + ")")
  }
}


输出结果为:
(13, 19)
(14, 18)
(15, 17)

可以看出,序列解析并不仅仅限制为列表,前面的程序使用了迭代。每种支持filter,map和flatMap操作的数据类型都可以用于序列解析。

序列解析还可以没有返回,即返回Unit。编码的时候去除yield关键词即可。与上面代码等效的代码如下:
object ComprehensionTest3 extends Application {
  for (i <- Iterator.range(0, 20);
       j <- Iterator.range(i + 1, 20) if i + j == 32)
    println("(" + i + ", " + j + ")")
}




你可能感兴趣的:(Scala之旅 7 序列解析(Sequence Comprehension))