December 4th, 2009

stupid

New lows in ActionScript 3: for each(... in ...) assumes it's iterating over a const array


checking objects (0) on shelf_gas
checking objects (0) on shelf_liquid
checking objects (3) on shelf_solid
Water
MtDew
Mercury

checking Water
Water is on the wrong shelf - moving it back to the desk.
clean(): removing Water
addObj(): set Y coord
addObj(): only one object on shelf

checking Mercury
Mercury is on the wrong shelf - moving it back to the desk.
clean(): removing Mercury
addObj(): set Y coord
addObj(): spliced in Mercury
addObj(): done with insert, now resolving overlaps.


Notice that it shows MtDew is on the shelf... but somehow it never tests MtDew to see what phase of matter it is?

The code looks something like:

var dobj:DisplayObject;
for each(dobj in shelf.objsOnMe)
{
  trace("checking " + dobj.name);
  if(IPhase(dobj).phase != correctPhase)
  {
   // Move object back to desk.
   trace(dobj.name + " is on the wrong shelf - moving it back to the desk.");
   dobj.x = desk.x + 1;
   dobj.y = desk.y - 1; // one pixel above bottom of desk's droptarget
   shelf.clean();
   desk.addObj(dobj);
  }
}


The key thing here is shelf.clean(), which removes dobj from the shelf's objsOnMe array. But the for each loop is keeping a hidden index behind the scenes, which doesn't update when the objsOnMe's length changes. Thus, an item is skipped.

C++ and Java both had to deal with this a long, long time ago. They're bright enough to create an iterator on the array/collection you're iterating over, and then calling iter.getNext() to grab the next object. This avoids the problem entirely. Adobe, however, being eternally blind to the lessons of history, couldn't figure this out. In fact, I doubt they even know the problem exists. So shockingly intelligent you are, Adobe...

Don't bother looking up the docs for "for each" - they don't say anything about this. Of course they don't. You expect Adobe's docs to be worth a god damn this time, when they never have been before?

TL;DR - DO NOT use for each(... in ...) in AS3 if you plan to add/remove items from the array/collection you're iterating over! It will fuck up, skip items, and you won't have any idea why.
  • Current Music
    No Fun At All - Lessons Never Learned