Scala - difference between for each loops

本秂侑毒 提交于 2021-02-16 06:12:46

问题


Is there any difference between the two following statements. They achieve the same end, correct? Do they compile to the same Java code? Is there any performance difference between them or is it just a matter of preference/readability?

for (thing <- things) {
    doSome(thing)
}

things.foreach(
  thing =>
    doSome(thing)
)

回答1:


for comprehensions are defined as simple syntactic translations. That's extremely important, because that allows any object to work with for comprehensions, it just has to implement the right methods.

IOW: the Scala Language Specification says that the first snippet gets translated into the second. So, if there were any difference whatsoever between the two snippets, that would be a violation of the spec and thus a very serious compiler bug.

Some people have asked for, and even implemented, special treatment of certain objects (e.g. Ranges), but those patches were always rejected with the argument that special treatment for special types would only benefit those special types, whereas making Scala faster in general will benefit everybody.

Note that with Macros, it's probably possible to detect, say, iteration over a Range purely as a simple C style for loop and transform that into a while loop or a direct tailrecursive inner function, without having to change the spec or add special casing to the compiler.




回答2:


They are identical. Given

class Foreach {
  val things = List(1,2,3)
  def doSome(i: Int) { println(i) }
  def one { for (thing <- things) { doSome(thing) } }
  def two { things.foreach{ thing => doSome(thing) } }
}

the bytecode is

public void one();
  Code:
   0:   aload_0
   1:   invokevirtual   #40; //Method things:()Lscala/collection/immutable/List;
   4:   new #42; //class Foreach$$anonfun$one$1
   7:   dup
   8:   aload_0
   9:   invokespecial   #46; //Method Foreach$$anonfun$one$1."<init>":(LForeach;)V
   12:  invokevirtual   #52; //Method scala/collection/immutable/List.foreach:(Lscala/Function1;)V
   15:  return

public void two();
  Code:
   0:   aload_0
   1:   invokevirtual   #40; //Method things:()Lscala/collection/immutable/List;
   4:   new #55; //class Foreach$$anonfun$two$1
   7:   dup
   8:   aload_0
   9:   invokespecial   #56; //Method Foreach$$anonfun$two$1."<init>":(LForeach;)V
   12:  invokevirtual   #52; //Method scala/collection/immutable/List.foreach:(Lscala/Function1;)V
   15:  return



回答3:


Per scala-lang.org:

As always, for-expressions can be used as an alternate syntax for expressions involving foreach, map, withFilter, and flatMap, so yet another way to print all elements returned by an iterator would be:

for (elem <- it) println(elem)

"Alternate syntax" would mean identical.




回答4:


Basically

a for loop is a construct that says

perform this operation n. times

a foreach loop is a construct that says

perform this operation against each value/object



来源:https://stackoverflow.com/questions/16743966/scala-difference-between-for-each-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!