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)
)
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With