AS3 SharedObject spooky array entanglement - arrays

var so:SharedObject = SharedObject.getLocal("example");
var arr:Array=[1,2,3];
so.data.arr = arr;
so.flush();
trace(so.data.arr); // outputs 1,2,3
arr[2]=5;
trace(so.data.arr); // outputs 1,2,5
As you see, I updated only arr, but so.data.arr got updated as well.
so.data.arr doesn't update if instead of arr[2]=5; i write arr=[1,2,5];
Seems that arr and so.data.arr are linked somehow, but only if I update an element in the arr, not set the whole arr differently.
I discovered this accidentally. Why is it working like that?
Can I count that it works like that every time and use it? Thanks.

Basically speaking arrays are passed by reference, not by value. That means if you assign an array variable to another one you are not creating a new array.
so.data.arr = arr;
means that both so.data.arr and arr point to the same array object. That's why modifications to either one will be reflected by the other. They are pointing at the same thing. But
arr=[1,2,5];
will make arr point to some other array object, remember that [1,2,5] is a short hand version of new Array(1,2,5).
That's why after that line they aren't "linked" any more.

Related

Mutability of the Iterator Element in a For-In loop with an Array in Swift

I have some code in Swift 3.0 like so for trying to update the property in a array of elements...
for point in listOfPoints {
var pointInFrame : Float = Float(point.position.x * sensorIncomingViewPortSize.width) + Float(point.position.y)
point.status = getUpdateStatus( pointInFrame )
}
However I get a compile error of:
'Cannot assign to property: 'point' is a 'let' constant' [for line 3]
Is there anyway to make the iterator (point) mutable in Swift, like how you can use 'inout' for a function parameter?
Or are you supposed to do this task another way?
Thanks in Advance.
Stan
Just change it to var instead of let where you declare point. let is a constant.
Another way to accomplish this:
for i in 0 ... myStructArray.count - 1 {
var st = myStructArray[i]
st.someStringVariable = "xxx" // do whatever you need with the struct
st.someIntVariable = 123 // do more stuff
// last step (important!):
myStructArray[i] = st // necessary because structs are VALUE types, not reference types.
}
If you only need to make one change, you can omit the steps of defining the local variable (st in the example) as the array element and then afterwards setting the array element as equal to the local variable. But if you're going to make lots of changes to the element, if may be cleaner to make the local variable, make all the changes to it, and then assign that variable back to the array element.
If the array was of a Class rather than a Struct, that last step of assigning back wouldn't be necessary (reference type -- Class, vs value type -- Struct).

AS3: How can you get an Array name from string

I am trying to copy a 2D array in a temporary array to a permanent one. The problem is that the array it's trying to copy to is dynamic.
I was looking for a way to get string (the new arrays name) to act as the arrays actual name, not the value of any part of the array. I have looked around and this is roughly what I came to:
(this["dynamicArrayName"]) = tempArray;
or
(this[variableWithName]) = tempArray;
(not even sure thats the best way to copy a 2D array).
However, this doesn't work :(. It comes up with so many errors (not syntax).
If there is some way to turn string into an Arrays/Variables name, it would be fantastic to know about.
Just drop the parens in your first example.
function someFunc():void {
var temp:Array = [1,2,3];
this['someArr'] = temp;
}
trace(this['someArr']);
// will output "undefined"
someFunc();
trace(this['someArr']);
// will output "1,2,3"

(AS3) Two arrays associated? Change on one changes the other

When I splice an entry from my one array, it splices the same entry from my other array... What is happening?
private static var words:Array = new WordFile().toString().split(/\n/);
private static var wordsTemp:Array;
public static function checkWord (word:String):Boolean
{
var truefalse:Boolean = wordsTemp.indexOf(word+"\r".toLowerCase()) > -1;
trace (words.length)
wordsTemp.splice(wordsTemp.indexOf(word+"\r".toLowerCase()), 1);
trace (words.length)
return truefalse
}
public static function resetArrays :void
{
wordsTemp = words
}
With this code, I call the resetArrays function every time a new game is started. Once in the game, the program will call checkWord with a word being passed to it. If it is found in the word array, it will splice it from the temporary array. However, when I run it, the 2 traces yield 2 different numbers, with the second one being one lower (assuming the word was found in the array). This seems to me to be very strange as I am splicing the temporary array that gets reset, however when tracing the array that is supposed to be unchanged (there is no operations other than the ones I am showing you with it in it) it seems to be changed by a splice in the temporary array...
Any thoughts?
In AS3, all data types except String and Number (and related) are copied by reference
This means that it only copies a reference to the original object when you use myArray1 = myArray2
In more detail, consider the memory at which words is stored is 0x123456
wordsTemp = words will make wordsTemp point to the same memory, i.e. 0x123456
When you do any operation on words, the array at 0x123456 is modified. But this is what wordsTemp refers to. So in reality both are the same object. To make both different, you need to clone the object. In case of an array, you can clone it using any method that modifies the array and returns the new array, e.g. Array.slice
wordsTemp=words.slice(0, words.length); //will do the trick
Or, you could concatenate nothing to the original array and get a duplicate
wordsTemp=words.concat();
Alternatively, if you want to write more lines of code, here's what you can do:
wordsTemp=new Array();
for (var i:int=0; i<words.length; i++) {
wordsTemp.push(words[i]);
}
When you do wordsTemp = words, you don't just assign the array item, but the memory space in the program. You have to copy all item from the first array to the second, but not set it equal has you do.
You can do a loop to copy all item from words to wordsTemp or do something like :
wordsTemp = words.slice(0, words.length);
It will return a copy of the original array without modifying it
Hop that can help
As far as I know, the easiest and "standard" way to clone an array in AS3 is:
var cloneArray:Array = sourceArray.concat();

Interesting behaviour when using for-in constructs in CFScript

I noticed something interesting when using for-in constructs in cfscript: It appears that the variable in struct argument in the for(in) loop is set as an independent variable, and has no reference to its parent array key.
If you run the following code you will see the array doesn't change on output. The variable local.i inside the loop is being assigned the new value, but the array remains unchanged.
function arrayTest()
{
local.foo = ["bar-one","bar-two", "bar-three"];
for (local.i in local.foo)
{
local.i = "I am #local.i#";
// Dump local.i; its output will be 'I am bar-[one[two]] etc...'
}
// Dump local.i; its output will as above
// Dump the array; its keys remain unchanged: "bar-one, bar-two, -bar-three"
writeDump(local.foo);
}
So why is this? I know arrays are passed by reference in CF, but I'm not passing an array here. I'm just using one in a for-in construct. There is a difference, no?
It's a bit misleading to call the argument variable in structure. I see local.i as a shortcut to local.foo[ local.i ]. It sounds like the var is indeed the array key and we can modify it. The solution here is to use a plain for() loop, instead.
I would not expect the underlying array to change unless i was a complex object of some sort or something passed by reference. For example if foo were
local.foo = [{a="b"},{a="c"}];
then modifying local.i.a = "I am key #local.i.a#"; would modify the object within the array, and those changes would be reflected in your dump.
Update:
Ultimately this comes down to pointers or references. In loose terms, local.i is just a pointer to objects within the array. So resetting local.i just points that variable at some other object in memory. It has no impact on the array. Notice the change in hashcode value?
// example
local.foo = [ "bar-one" ];
for (local.i in local.foo)
{
WriteOutput("local.i (before) =#local.i.hashCode()#<br>"); //-335192660
WriteOutput("local.foo[1] = #local.foo[1].hashCode()#<br>");//-335192660
local.i = "I am key #local.i#";
WriteOutput("local.i (after) = #local.i.hashCode()#<br>"); //1075915694
}
writeDump(local.foo);

What does it mean for .slice() to be a "shallow clone"?

ActionScript's Array and Vector classes both have a slice() method. If you don't pass any parameters, the new Array or Vector is a duplicate (shallow clone) of the original Vector.
What does it mean to be a "shallow clone"? Specifically, what is the difference between
Array newArray = oldArray.slice();
Vector.<Foo> newVector = oldVector.slice();
and
Array newArray = oldArray;
Vector.<Foo> newVector = oldVector;
? Also, what if the Vector's base type isn't Foo, but something simple and immutable like int?
Update:
What is the result of the following?
var one:Vector.<String> = new Vector.<String>()
one.push("something");
one.push("something else");
var two:Vector.<String> = one.slice();
one.push("and another thing");
two.push("and the last thing");
trace(one); // something, something else, and another thing
trace(two); // something, something else, and the last thing
Thanks! ♥
In your context, what .slice() does is simply to make a copy of your vector, so that newArray refers to a different object from oldArray, except both seem like identical objects. Likewise goes for newVector and oldVector.
The second snippet:
Array newArray = oldArray;
Vector.<Foo> newVector = oldVector;
actually makes newArray a reference to oldArray. That means both variables refer to the same array. Same for newVector and oldVector — both end up referring to the same vector. Think of it as using a rubber stamp to stamp the same seal twice on different pieces of paper: it's the same seal, just represented on two pieces of paper.
On a side note, the term shallow copy differs from deep copy in that shallow is a copy of only the object while deep is a copy of the object and all its properties.
Also, what if the Vector's base type isn't Foo, but something simple and immutable like int?
It's the same, because your variables refer to the Vector objects and not their ints.
What is the result of the following?
Your output is correct:
something, something else, and another thing
something, something else, and the last thing
two = one.slice(), without any arguments, makes a new copy of one with all its current contents and assigns it to two. When you push each third item to one and two, you're appending to distinct Vector objects.

Resources