A strange way AS3 manages arrays
Today I was porting my Sudoku creator/solver with PHP in AS3 when I found this strange behavior.
I am calling it “strange behavior” because it’s not properly a bug… let’s say an issue.
Look at this script and its comments…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | package { import flash.display.Sprite; public class wtf extends Sprite { public function wtf() { var my_array = new Array(1,2,3); var my_saved_array = new Array(); trace(my_array); // 1,2,3 ... of course my_saved_array.push(my_array); trace(my_saved_array); // 1,2,3 ... of course my_array[2] = 4; trace(my_array); // 1,2,4 ... of course trace(my_saved_array); // 1,2,4 !!!! WHY? WHY? my_saved_array.push(my_array.slice()) trace(my_saved_array); // 1,2,4,1,2,4 ... dirty trick... my_array[2] = 5; trace(my_saved_array); // 1,2,5,1,2,4 ... yeah! } } } |
I wanted to save various instances of my_array in my_saved_array in order to make some backtracking, when I found push() does not save the array content but the array itself, so if I change some my_array values, the pushed array will also change.
You can prevent it by saving a copy of your original array like I did with slice().
This does not happen neither with Php nor, as far as I remember, with C
What I know, I had an hard time debugging the script I was writing…
They can be easily customized to meet the unique requirements of your project.
18 Responses to “A strange way AS3 manages arrays”
Leave a Reply
Trackbacks
-
Sudoku creator/solver with AS3 : Emanuele Feronato on
December 27th, 2008 3:10 pm
[...] after a little hassle due to a strange way AS3 manages arrays (in my opinion), I am ready to post the AS3 version of the [...]
Posts
- Rick Triqui: my first PlayCrafter game
- Prototype of a Flash game like Meeblings
- Games for the game developers!
- The art of debugging
- How to embed a text file in Flash
- Create a Flash game in minutes with PlayCrafter
- Upgrade your Flash CS4 to 10.0.2
- Play Mazeroll, my latest Box2D game
- Triqui MochiAds Arcade plugin for WordPress Released!!
- The MochiAds funnel
- Flash game creation tutorial - part 1
- Create a Lightbox effect only with CSS - no javascript needed
- Flash game creation tutorial - part 2
- Make a Flash game like Flash Element Tower Defense - Part 2
- Flash game creation tutorial - part 3
- Create a flash draw game like Line Rider or others - part 1
- Create a Flash Racing Game Tutorial
- Make a Flash game like Flash Element Tower Defense - Part 1
- Create a flash artillery game - step 1
- Create a flash draw game like Line Rider or others - part 5
- Flash game creation tutorial – part 5.2




(4.9 out of 5) - Flash game creation tutorial – part 3




(4.86 out of 5) - Creation of a platform game with Flash – step 2




(4.84 out of 5) - Create a survival horror game in Flash tutorial – part 1




(4.82 out of 5) - Create a flash artillery game – step 1




(4.82 out of 5) - Create a Flash Racing Game Tutorial




(4.8 out of 5) - Create a flash artillery game – step 2




(4.75 out of 5) - New tile based platform engine – part 6 – ladders




(4.74 out of 5) - Flash game creation tutorial – part 2




(4.73 out of 5) - The experiment – one year later




(4.7 out of 5)


that’s exactly the expected behavior and i don’t know how else you would expect it to work. arrays and other complex objects are always handled by reference. that’s how you get two dimensional arrays.
are you expecting it to push all the elements of the array as individual elements? i think your traces may be confusing you. for example, after line 11, the length of my_saved_array is 1. at the end, it is 2. my_saved_array contains two references to two separate arrays. one in element 0, one in element 1. but when you trace them, it can appear that you are tracing out one big array.
I was expecting 1,2,3 at line 16 and 1,2,3,1,2,4 at line 22
Php works this way.
You can’t really blame ActionScript for this one. PHP is full of these, imo, stupid design choices.
In ActionScript you always pass the reference of an object if it’s not a string, number or boolean. While it’s pretty stupid that you can’t pass a reference to any of these 3 types at least it’s easy to know what will happen. In PHP you mostly have to guess.
But after you run:
my_saved_array.push(my_array);
Then my_saved_array is:
[my_array]
i.e. it is an array and the first item in it is a reference to my_array… That is exactly what array.push is meant to do:
http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/Array.html#push()
It looks like you want to just copy the contents of my_array to my_saved_array? The easiest way to do that would be:
var my_saved_array:Array = my_array.concat();
If you there was already stuff in my_saved_array then you could do:
my_saved_array = my_array.concat(my_saved_array);
If I understand what you’re trying to do (keep a copy of an array at a certain point) I believe the recommended approach is to use the concat function:
http://livedocs.adobe.com/flex/3/langref/Array.html#concat()
The hell arrays.Linked lists all the way.
You’re assuming AS to automatically convert datatype of my_array when you are pushing to in my_saved_array and split it into pieces. That won’t happen.
By tracing my_saved_array, you get all elements in as ‘String’. And the first element, my_array, is also converted to string and so looks like 1,2,3 and later when you change value at position two, it traces 1,2,4.
I hope you my text here makes sense to you.
Happy Holidays to you and family.
Best.
Sam
To add to my above comment, what you want to achieve is possible with Array.concat() method. It takes another array and joins them. In this case, my_saved_array.concat(my_array);
That is a normal behavior in many languages. All you are doing is copying the pointer to the array, and not the array itself. It’s the same in AS2. And it’s the same for objects too.
To copy the contents you need to do it manually, like using slice, but even in that case, if your array, contains arrays, those will only be pointers to the original array.
So you need to make a copy function that nests through it. You can make a function for doing that for both objects and arrays. There are actually several examples you can find if you google it.
That remembers me a day I almost died with a project in java, it happens something similar.
Yeah, this is really a PHP thing. Most languages (Javascript included) work more like the way that AS3 does.
C doesn’t have built-in push / pop operators on it’s arrays, so its behavior would depend on whatever libraries you were using for list management.
I had this confusing issue once before, and it took a while to figure it out.
I thin it is actually much better this way however, so I am glad it does it.
I do wish you could pass primitives as reference like in C++ however…
Exactly, since you made a custom object you are sharing a reference. Really has nothing to do with Arrays and just the way AS handles variable assignments for anything except String, Boolean, Number, int, and uint. I did not know PHP treats assignments differently. Good to know. Thanks :)
[code]
var aNum:uint = 0
var bNum:uint = aNum
trace (aNum) //0
trace (bNum) //0
aNum = 2
trace (aNum) //2
trace (bNum) //0
[/code]
the only problem here was that you approached this situation with wrong expectations.
your php background experience didn’t help you here.
i’ve once felt in this kind of situation and then i found out about the concat method.
HEAD UP !!! :)
With PHP you explicitly tell a variable to pass by reference. If I remember correctly this is done as follows:
// Changes to $myArr2 no affect on $myArr1
$myArr2 = $myArr1;
// Changes to $myArr3 affect $myArr1
$myArr3 = &$myArr1;
Agreed that concat() should be used for “copying” an array and breaking the reference. Can’t find the posting with some speed tests but concat() proved to be the fastest method.
Have to somewhat disagree that PHP offers a poor design decision on how it assigns complex types. It’s all a matter of the “default” for both languages, PHP doesn’t lack the ability to assign by reference, it just isn’t the default behavior.
Best,
-michael
lol… public function wtf(){
ok he was just showing something he thought was curious, why are you guy blaming him?
remember, not even a PROgrammer knows all tricks!