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:

  1. Why events suck in ActionScript 3

Category: AS3 6 comments »

6 Responses to “For-each-in loops in ActionScript 3”

  1. Top 6 AS3 features you miss when switching back to AS2 | Barklund.org

    [...] 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 [...]

  2. Semester 2 - Week 2: AS3 Properties, Methods and Events « Flash Uni

    [...] http://www.barklund.org/blog/2009/05/21/for-each-in-loops-in-actionscript-3/ [...]

  3. Greg

    You can use dynamic typing in a for each in loop by setting your type to *. For example:

    var arry:Array = ["1", 2, "3"];

    for each (var item:* in array)
    {
    if (item is String)
    {
    trace(“String value is: ” + item);
    }
    else if (item is Number)
    {
    trace(“Number value is: ” + item);
    }
    }

    // returns
    // String value is: 1
    // Number value is: 2
    // String value is: 3

  4. Zwaf

    Not sure whether I’m bumping up an old topic but this is just about the only reference to for-each loops in AS3 I can find on google.

    Why does for-each looping not work for children of displayObject

    for each(var child:Sprite in childContainer)
    {
    removeChild(child);
    }

    I know the alternative is iterating through all children (i=0;i<numChildren;i++) and a removeChildAt but this does not work for me as the index of the container is messed up (a child might be on 2 and none on 0) which will cause this procedure to throw errors.
    Plus that 'for each' looks much more elegant to me.

    Thanks in advance

  5. Barklund

    Hi Zwaf,

    For each is not a generic iterator method for iterating over contents of a collection (like loops in Java or Python). It is only possible to use for iterating over all members of a basic object that is as close to being array-like as they come.

    If you have the need for iterating over your children, just manually maintain a list of them and you can iterate all you like :)

  6. bas

    please use xmllist. it’s super handy!


Leave a Reply



Back to top

     

Get Adobe Flash playerPlugin by wpburn.com wordpress themes