For-each-in loops in ActionScript 3
For-each-in is quite a secret looping method in ActionScript. It was added in ActionScript 3 in Flash Player 9 (actually in the 8.5 release). It has existed in other languages like PHP for quite some time, and Java has a similar iteration method added in recent years. It is ideal for looping over arrays of similar-typed elements, as it loops over values, not keys.
The for-in loop iterates over keys like this:
var items:Array = ["hi", "there", "bob"]; for (var index in items) { trace(index+" => "+items[index]); // traces "0 => hi", "1 => there" and "2 => bob" }
The problem with this construct is, that it is actually meant to loop over properties of an object, not indexes of an array. This can be seen by the strange typing requirement – if I wanted to type the value of index in the above (which I really ought to), it must be typed as a String:
var items:Array = ["hi", "there", "bob"]; for (var index:String in items) { trace(index+" => "+items[index]); // traces "0 => hi", "1 => there" and "2 => bob" }
If it was typed as a number, the compile-time validator would report an error:
1067: Implicit coercion of a value of type String to an unrelated type Number.
This makes the for-in loop quite flawed for array iteration.
The for-each-in loop however loops over values:
var items:Array = ["hi", "there", "bob"]; for each (var value:String in items) { trace(value); // traces "hi", "there" and "bob" } var numbers:Array = [2, 3, 5, 7]; for each (var prime:uint in numbers) { trace(prime); // traces 2, 3, 5 and 7 }
For these simple-valued arrays it might not seem like it matters, but what if we were working on an array of objects; maybe a list of XML nodes:
var books:XML = <books> <book> <author>John Smith</author> <title>The Book About Nothing</title> </book> <book> <author>Jane Doe</author> <title>The Book About Everything</title> </book> </books>; for each (var book:XML in books.book) { trace(book.author); // traces "John Smith" and "Jane Doe" }
See how nice it is? There is however no compile-time validation of the type of the iterator variable (value in the above code), and this compiles just fine (but throws an error during execution):
for each (var book:Sprite in books.book) { trace(book); // this is never reached }
But then comes the new Vector-type. Vector is generic, which means it can be typed to reflect the values:
var books:Vector.<XML> = new Vector.<XML>(); books.push(<book><author>John Smith</author><title>The Book About Nothing</title></book>); books.push(<book><author>Jane Doe</author><title>The Book About Everything</title></book>); for each (var book:XML in books) { trace(book.author); // will again correctly trace authors }
I for one hoped, that this for-each-in loop would be type-checked at compile-time to verify, that my iterator variable had the same type as the elements of the Vector, but no, I can still change the type to e.g. Sprite and it compiles just fine (but of course still causes an error at execution). This is a clear weakness compared to the Java for-each loop, which does exactly that – checks the type of the iterator variable compared to the generic type of the iterable list.
One final note about the secret loop is, that the built-in editor in Flash CS4 does not highlight the word “each” as a keyword, which is quite strange. I can even use the word “each” as a variable name, which I clearly cannot with e.g. “while”, “for”, “function” or other reserved keywords. It seems like it is not a “real” keyword, just some extra word that can be appended to “for” and have a special meaning when present. Oh, and as can be seen here, the GeShi syntax highlighter doesn’t highlight it either ;) (UPDATE: Well, I if switched highlighting to AS3 it worked, so actually that was my own fault).
Nevertheless, for-each-in loops are a great asset and especially when working with XML and the new notation E4X for XML traversal.
Related posts:
Category: AS3 2 comments »
July 19th, 2009 at 23:41
[...] latter category includes e.g. the for-each-in construct, different number types, class introspection or built-in class look-up by string, but these are my [...]
August 4th, 2009 at 08:32
[...] http://www.barklund.org/blog/2009/05/21/for-each-in-loops-in-actionscript-3/ [...]