Scala - difference between for each loops
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
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. Range
s), 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.