Scala Comprehensions

原创转载请注明出处:http://agilestyle.iteye.com/blog/2333647

for和if的组合称为for推导,简称为推导。先看一个简单的例子:

package org.fool.scala.comprehension

object ComprehensionTest extends App {
  def evenGT5(v: Vector[Int]): Vector[Int] = {
    // 'var' so we can reassign 'result'
    var result = Vector[Int]()

    for {
      n <- v
      if n > 5
      if n % 2 == 0
    } result = result :+ n

    result
  }

  val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 15, 17, 20)
  println(evenGT5(v))
}

Note:

result为var而不是val

Vector有一个操作符“:+”,它会接受一个Vector(但是不会修改它),并将操作符右边的元素与其组合起来,以此创建一个新的Vector。

Console Output


 

有一种将result用作val(而不是var)的方式:by building result "in place" rather than creating it piece-by-piece。为了实现这个目的,可是使用Scala的yield关键字。当你声明yield n时,它会将值n "yield up"出来,使其成为result的一部分。

package org.fool.scala.comprehension

object Yielding extends App {
  def yielding(v: Vector[Int]): Vector[Int] = {
    val result = for {
      n <- v
      if n < 10
      if n % 2 != 0
    } yield n
    result
  }

  val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 15, 17, 20)
  println(yielding(v))
}

Console Output


 

接下来在推导内部定义值,并且不存储和返回中间结果result

package org.fool.scala.comprehension

object Yielding2 extends App {
  def yielding2(v: Vector[Int]): Vector[Int] = {
    for {
      n <- v
      if n < 10
      isOdd = (n % 2 != 0)
      if (isOdd)
    } yield n
  }

  val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 15, 17, 20)
  println(yielding2(v))
}

Console Output


 

与其他任何表达式一样,yield表达式也可以组合

package org.fool.scala.comprehension

object Yielding3 extends App {
  def yielding3(v: Vector[Int]): Vector[Int] = {
    for {
      n <- v
      if n < 10
      isOdd = (n % 2 != 0)
      if (isOdd)
    } yield {
      // only inside the comprehension can you get away without declaring val or var for new identifiers.
      val u = n * 10
      u + 2
    }
  }

  val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 15, 17, 20)
  println(yielding3(v))
}

Note:

只有在推导内部才能不为新标识符声明val或var

Console Output


 

可以将一个推导只与一个yield表达式相关联,并且不能将yield表达式置于推导体之前。但是推导可以嵌套:

package org.fool.scala.comprehension

object Yielding4 extends App {
  def yielding4(v: Vector[Int]) = {
    for {
      n <- v
      if n < 10
      isOdd = (n % 2 != 0)
      if (isOdd)
    } yield {
      for (u <- Range(0, n))
        yield u
    }
  }

  val v = Vector(1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 13, 15, 17, 20)
  println(yielding4(v))
}

Console Output


 

参考资料:

Scala编程思想 

猜你喜欢

转载自agilestyle.iteye.com/blog/2333647