Thanks for looking at the problem and suggesting a workaround.

- rod

--- In [email protected], "Gordon Smith" <[EMAIL PROTECTED]> 
wrote:
>
> > I forwarded this to a compiler engineer. 
>  
> He says that it looks like a compiler bug, but he thinks he found a
> workaround: Don't name the three Function objects in 
verifyContainer().
> For example, instead of passing
>  
>     function myContainerFunction( itemNo : int, numItems : int, 
items :
> Array ) : Boolean { ... }
> 
> to enumerateItems(), pass
>  
>     function( itemNo : int, numItems : int, items : Array ) : 
Boolean {
> ... }
>  
> He said this seems to make it work.
>  
> - Gordon
>  
> ________________________________
> 
> From: Gordon Smith 
> Sent: Tuesday, March 27, 2007 8:55 PM
> To: '[email protected]'
> Subject: RE: [flexcoders] Re: Bad Results referencing local 
variables in
> nested loops
> 
> 
> I noticed two peculiarities in your code: You declare
> myAnimationFunction() and myEventFunction() in verifyContainer() to
> return void rather than Boolean. But when I declare them to return
> Boolean and actually return true, I still see your problem.
>  
> In stepping through it in the FlexBuilder debugger, it appears 
that the
> scope chain is different when the second item is processed than 
when the
> first one was. I think you've found an AS3 compiler codegen bug
> involving nested anonymous functions. I'll forward this to a 
compiler
> engineer.
>  
> - Gordon
> 
> ________________________________
> 
> From: [email protected] 
[mailto:[EMAIL PROTECTED] On
> Behalf Of Rod Perkins
> Sent: Tuesday, March 27, 2007 5:48 PM
> To: [email protected]
> Subject: [flexcoders] Re: Bad Results referencing local variables 
in
> nested loops
> 
> 
> 
> I had a typo in the post for a line in the setup function. The 
line:
> 
> "[v:" + vItemNo + " i:" + itemNo + " a: " + aItemNo + " e: " + 
> eItemNo + "]"
> 
> should be:
> 
> "[v:" + pageNo+ " i:" + itemNo + " a: " + aItemNo + " e: " + 
eItemNo 
> + "]"
> 
> - rod
> 
> --- In [email protected] <mailto:flexcoders%
40yahoogroups.com>
> , "Rod Perkins" <rperkins@> 
> wrote:
> >
> > 
> > I have been having a great time using ActionScript 3.0 and Flex 
> but 
> > I have encountered problems which seem to be caused by 
Flexbuilder 
> > or the Flashplayer runtime. The following problem is based on a 
> > situation I have in my application uses a data structure of 
> embedded 
> > objects. I replicated the problem using arrays instead of the 
> > classes I had used. The example may seemed contrived but 
> reproduces 
> > the problem without duplicating the complexity of my application.
> > 
> > The structure was based on data structure of page objects, which 
> > contains several cell items. Each item has a list of animations, 
> > and each animation has a list trigger events references. So the 
> > nested structure looked like the following:
> > 
> > Pages (instance 1)
> > Item (instance 1)
> > Animation (instance 1)
> > Events (instance 1)
> > Events (instance 2)
> > Animation (instance 2)
> > Events (instance 1)
> > Events (instance 2)
> > Item (instance 2)
> > Animation (instance 1)
> > Events (instance 1)
> > Events (instance 2)
> > Animation (instance 2)
> > Events (instance 1)
> > Events (instance 2)
> > 
> > The setup function in my example creates this structure using 
> > arrays. The function "goodResult" traverses the structure using 
> > nested for-loops. Nested local variables at different scoping 
> > levels are referenced and displayed during the inner most loop 
for 
> > the Events (instance 1 & 2). This produces the expected result. 
> > Good Results
> > 500 200 [v:0 i:0 a: 0 e: 0]
> > 500 200 [v:0 i:0 a: 0 e: 1]
> > 500 200 [v:0 i:0 a: 1 e: 0]
> > 500 200 [v:0 i:0 a: 1 e: 1]
> > 500 200 [v:0 i:1 a: 0 e: 0]
> > 500 200 [v:0 i:1 a: 0 e: 1]
> > 500 200 [v:0 i:1 a: 1 e: 0]
> > 500 200 [v:0 i:1 a: 1 e: 1]
> > 
> > The "badResult" function traverses the structure using the OO 
> > technique of enumeration (iterator) functions. Among other 
> reasons, 
> > I used this approach to make the code more readable and compact 
by 
> > hiding the loop from the caller and the typecasting the values 
> > automatically. The caller is required to send a Function which 
is 
> > then called during each pass (iterator) ofthe loop. The nested 
> > local variables this time are not displayed properly. During the 
> > first call, the results for Events (instance 1) is correct, but 
> > Events (instance 2) is incorrect. Subsequent calls to 
> > the "badResult" function display erroneous results. 
> > 
> > Bad Results - first iteration - first event loop good, second 
loop 
> > bad
> > 500 200 [v:0 i:0 a: 0 e: 0]
> > 500 200 [v:0 i:0 a: 0 e: 1]
> > 500 200 [v:0 i:0 a: 1 e: 0]
> > 500 200 [v:0 i:0 a: 1 e: 1]
> > 500 59369881 [v:0 i:1 a: 0 e: 0]
> > 500 59369881 [v:0 i:1 a: 0 e: 1]
> > 500 59369881 [v:0 i:1 a: 1 e: 0]
> > 500 59369881 [v:0 i:1 a: 1 e: 1]
> > Bad Results - second iteration - both loops bad
> > 2 500 [v:0 i:0 a: 0 e: 0]
> > 2 500 [v:0 i:0 a: 0 e: 1]
> > 2 500 [v:0 i:0 a: 1 e: 0]
> > 2 500 [v:0 i:0 a: 1 e: 1]
> > 2 500 [v:0 i:1 a: 0 e: 0]
> > 2 500 [v:0 i:1 a: 0 e: 1]
> > 2 500 [v:0 i:1 a: 1 e: 0]
> > 2 500 [v:0 i:1 a: 1 e: 1]
> > Bad Results - third iteration - both loops bad
> > 2 500 [v:0 i:0 a: 0 e: 0]
> > 2 500 [v:0 i:0 a: 0 e: 1]
> > 2 500 [v:0 i:0 a: 1 e: 0]
> > 2 500 [v:0 i:0 a: 1 e: 1]
> > 2 500 [v:0 i:1 a: 0 e: 0]
> > 2 500 [v:0 i:1 a: 0 e: 1]
> > 2 500 [v:0 i:1 a: 1 e: 0]
> > 2 500 [v:0 i:1 a: 1 e: 1]
> > 
> > I don't know if the problem is with the enumeration function 
calls 
> > or stack references during nested scope (this is not recursion 
so 
> > the stack depth should not be that great). The example is simple 
> so 
> > you can play around with it. It does make me worry about using 
> > Functions or nested function calls.
> > 
> > Here is the code for the example.
> > 
> > Regards,
> > 
> > Rod Perkins
> > 
> > ---------------------------
> > package 
> > {
> > 
> > import flash.display.Sprite;
> > import flash.events.Event;
> > 
> > public class BuildError_2 extends Sprite
> > {
> > private var _pages : Array = new Array();
> > 
> > public function enumerateEvents( _events : Array, func : 
> > Function ) : void
> > {
> > for ( var x : int = 0, numItems : int = 
> > _events.length; x < _events.length; x++)
> > {
> > var eventObj : Object = Object( 
> > _events[x] );
> > if (func.call( this, x, numItems, 
> > eventObj ) == false) break;
> > }
> > }
> > 
> > public function enumerateAnimations( _anim : Array, func : 
> > Function ) : void
> > {
> > for ( var x : int = 0, numItems : int = 
> > _anim.length; x < _anim.length; x++)
> > {
> > var animObj : Object = Object( _anim
> > [x] );
> > if (func.call( this, x, numItems, 
> > animObj ) == false) break;
> > }
> > }
> > 
> > public function enumerateItems( _items : Array, 
> > func : Function ) : void
> > {
> > for ( var x : int = 0, numItems : int = 
> > _items.length; x < numItems; x++)
> > {
> > var itemObj : Object = _items[x];
> > if (func.call( this, x, numItems, 
> > itemObj ) == false) break;
> > }
> > }
> > 
> > 
> > public function setup() : void
> > {
> > _pages = new Array();
> > for ( var pageNo : int = 0; pageNo < 1; 
> > pageNo++)
> > {
> > var _items : Array = new 
> > Array();
> > for ( var itemNo : int = 0; 
> > itemNo < 2; itemNo++)
> > {
> > var _anim : Array = 
> > new Array();
> > for ( var aItemNo : 
> > int = 0; aItemNo < 2; aItemNo++)
> > { 
> > 
> > var 
> > _events : Array = new Array();
> > for ( var 
> > eItemNo : int = 0; eItemNo < 2; eItemNo++)
> > { 
> > 
> > 
> > _events.push(
> > 
> > "[v:" + vItemNo + " i:" + itemNo + " a: " + aItemNo + " e: " 
> > + eItemNo + "]"
> > );
> > }
> > _anim.push( 
> > _events );
> > }
> > _items.push( _anim );
> > }
> > _pages.push( _items );
> > }
> > }
> > 
> > public function verifyContainer( container : 
> > Array ) : void
> > {
> > enumerateItems
> > (
> > container,
> > function myContainerFunction( 
> > itemNo : int, numItems : int, items : Array ) : Boolean
> > {
> > var itemCount : int = 500; 
> > 
> > enumerateAnimations
> > (
> > items,
> > function 
> > myAnimationFunction( animNo : int, numItems : int, anim : 
> Array ) : 
> > void
> > {
> > var 
> > animationDuration : int = 200; 
> > 
> > 
> > enumerateEvents
> > (
> > anim,
> > 
> > function myEventFunction( eventNo : int, numItems : int, 
> > event : Object ) : void
> > {
> > 
> > trace( itemCount + " " + animationDuration + " " + event);
> > }
> > );
> > }
> > );
> > 
> > return true;
> > }
> > );
> > 
> > }
> > 
> > public function goodResults() : void
> > {
> > for ( var pageNo : int = 0; pageNo < 
> > _pages.length; pageNo++)
> > {
> > var _items : Array = _pages[ 
> > pageNo ] as Array;
> > for ( var itemNo : int = 0; itemNo < 
> > _items.length; itemNo++)
> > {
> > var itemCount : int = 500; 
> > 
> > var _anim : Array = _items[ 
> > itemNo ] as Array;
> > for ( var aItemNo : int = 0; 
> > aItemNo < _anim.length; aItemNo++)
> > { 
> > 
> > var 
> > animationDuration : int = 200; 
> > 
> > var _events : Array 
> > = _anim[ aItemNo ] as Array;
> > for ( var eItemNo : 
> > int = 0; eItemNo < _events.length; eItemNo++)
> > { 
> > 
> > trace( 
> > itemCount + " " + animationDuration + " " + _events[eItemNo] );
> > }
> > }
> > }
> > }
> > }
> > 
> > public function badResults() : void
> > {
> > for ( var index : int = 0; index < 
> > _pages.length; index++)
> > {
> > var container : Array = _pages
> > [index] as Array;
> > 
> > verifyContainer( container );
> > }
> > }
> > 
> > public function BuildError_2()
> > {
> > setup(); 
> > 
> > trace("Good Results" );
> > // this path will print good results
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > goodResults();
> > 
> > trace("Bad Results - first iteration - first 
> > event loop good, second loop bad" );
> > // this path will print bad results
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 200
> > // 500 59435417
> > // 500 59435417
> > // 500 59435417
> > // 500 59435417
> > badResults();
> > 
> > trace("Bad Results - second iteration - both 
> > loops bad" );
> > // this path will print worse results 
> > traversing the same structure
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > badResults();
> > 
> > trace("Bad Results - third iteration - both 
> > loops bad" );
> > // this path will print the same results as 
> > the second iteration
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > // 2 500
> > badResults();
> > }
> > }
> > }
> > 
> > Rod Perkins
> > Principle Architect & Designer
> > Yahoo! Inc.
> > 701 First Avenue
> > Sunnyvale, CA 94089
> > 408.349.2766 (tel)
> > 409.349.7170 (fax)
> > rperkins@
> >
>


Reply via email to