Scala的for / yield原因中的赋值表达式?

时间:2015-03-01 08:27:45

标签: scala functional-programming for-comprehension

我的代码如下:

  type Occurrences = List[(Char, Int)]
  def subtract(x: Occurrences, y: Occurrences): Occurrences = for {
    (theChar, theInt) <- x
    yMap = y.toMap
    finalInt = theInt - yMap.getOrElse(theChar,0)
    if finalInt != 0
  } yield (theChar, finalInt)

我想知道yMap= y.toMap是仅被评估一次还是多次..如果对它进行了多次评估,那么只评估一次的正确语法是什么?

2 个答案:

答案 0 :(得分:3)

简答

只需将ymap = y.toMap部分从for理解中删除。

def subtract(x: Occurrences, y: Occurrences): Occurrences = {
    val yMap = y.toMap
    for {
      (theChar, theInt) <- x
      finalInt = theInt - yMap.getOrElse(theChar, 0)
      if finalInt != 0
    } yield (theChar, finalInt)
  }

详细答案

Scala For Comprehensions只是一种语法糖。

例如,您的代码将由编译器转换为以下代码(不完全是以下代码,但概念是相同的):

def subtract(x: Occurrences, y: Occurrences): Occurrences = x map {
    case (theChar, theInt) =>
      def yMap = y.toMap
      def finalInt = theInt - yMap.getOrElse(theChar, 0)
      (theChar, finalInt)
  } filter {
    case (_, theInt) =>
      theInt != 0
  }

因此,map部分中的任何表达式都将针对集合中的每个项目执行(在本例中为x)。通过将y = y.toMap部分移出for块,代码将被转换为:

  def subtract(x: Occurrences, y: Occurrences): Occurrences = {
    def yMap = y.toMap
    x map {
      case (theChar, theInt) =>
        def finalInt = theInt - yMap.getOrElse(theChar, 0)
        (theChar, finalInt)
    } filter {
      case (_, theInt) =>
        theInt != 0
    }
  }

这很可能是你真正想要的。

答案 1 :(得分:1)

x的每个元素进行一次评估; (theChar, theInt) <- x下面的所有是。

如果您只想评估一次,请将其保留在循环每个元素的任何内容之外。例如,

def subtract(x: Occurrences, y: Occurrences): Occurrences = {
  val yMap = y.toMap
  for {
    (theChar, theInt) <- x
    finalInt = theInt - yMap.getOrElse(theChar,0)
    if finalInt != 0
  } yield (theChar, finalInt)
}

会做到这一点。