Scala for 循环内的赋值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6447631/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 03:07:39  来源:igfitidea点击:

Value assignment inside for-loop in Scala

scalafor-loop

提问by Felipe Hummel

Is there any difference between this code:

这段代码有什么区别:

    for(term <- term_array) {
        val list = hashmap.get(term)
        ...
    }

and:

和:

    for(term <- term_array; val list = hashmap.get(term)) {
        ...
    }

Inside the loop I'm changing the hashmap with something like this

在循环内部,我正在用这样的东西更改哈希图

hashmap.put(term, string :: list)

While checking for the head of listit seems to be outdated somehow when using the second code snippet.

list使用第二个代码片段时,检查它的头部似乎已经过时了。

采纳答案by rafalotufo

Instantiating variables inside for loops makes sense if you want to use that variable the forstatement, like:

如果您想在for语句中使用该变量,则在 for 循环中实例化变量是有意义的,例如:

for (i <- is; a = something; if (a)) {
   ...
}

And the reason why your list is outdated, is that this translates to a foreachcall, such as:

您的列表已过时的原因是,这会转化为foreach调用,例如:

term_array.foreach {
   term => val list= hashmap.get(term)
} foreach {
  ...
}

So when you reach ..., your hashmap has already been changed. The other example translates to:

因此,当您到达...时,您的哈希图已经更改。另一个示例转换为:

term_array.foreach {
   term => val list= hashmap.get(term)
   ...
}

回答by kiritsuku

The difference between the two is, that the first one is a definition which is created by pattern matching and the second one is a value inside a function literal. See Programming in Scala, Section 23.1 For Expressions:

两者之间的区别在于,第一个是通过模式匹配创建的定义,第二个是函数字面量内的值。有关表达式,请参阅Scala 编程,第 23.1 节

  for {
    p <- persons              // a generator
    n = p.name                // a definition
    if (n startsWith "To")    // a filter
  } yield n

You see the real difference when you compile sources with scalac -Xprint:typer <filename>.scala:

当您使用以下命令编译源代码时,您会看到真正的区别scalac -Xprint:typer <filename>.scala

object X {
  val x1 = for (i <- (1 to 5); x = i*2) yield x
  val x2 = for (i <- (1 to 5)) yield { val x = i*2; x }
}

After code transforming by the compiler you will get something like this:

编译器对代码进行转换后,您将得到如下结果:

private[this] val x1: scala.collection.immutable.IndexedSeq[Int] =
  scala.this.Predef.intWrapper(1).to(5).map[(Int, Int), scala.collection.immutable.IndexedSeq[(Int, Int)]](((i: Int) => {
    val x: Int = i.*(2);
    scala.Tuple2.apply[Int, Int](i, x)
  }))(immutable.this.IndexedSeq.canBuildFrom[(Int, Int)]).map[Int, scala.collection.immutable.IndexedSeq[Int]]((
    (x: (Int, Int)) => (x: (Int, Int) @unchecked) match {
      case (_1: Int, _2: Int)(Int, Int)((i @ _), (x @ _)) => x
    }))(immutable.this.IndexedSeq.canBuildFrom[Int]);

private[this] val x2: scala.collection.immutable.IndexedSeq[Int] =
  scala.this.Predef.intWrapper(1).to(5).map[Int, scala.collection.immutable.IndexedSeq[Int]](((i: Int) => {
    val x: Int = i.*(2);
    x
  }))(immutable.this.IndexedSeq.canBuildFrom[Int]);

This can be simplified to:

这可以简化为:

val x1 = (1 to 5).map {i =>
    val x: Int = i * 2
    (i, x)
  }.map {
    case (i, x) => x
  }

val x2 = (1 to 5).map {i =>
    val x = i * 2
    x
  }