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: flexcoders@yahoogroups.com [mailto:[EMAIL PROTECTED] On
Behalf Of Rod Perkins
Sent: Tuesday, March 27, 2007 5:48 PM
To: flexcoders@yahoogroups.com
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 flexcoders@yahoogroups.com <mailto:flexcoders%40yahoogroups.com>
, "Rod Perkins" <[EMAIL PROTECTED]> 
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)
> [EMAIL PROTECTED]
>



 

Reply via email to