For-Each Loop AS3: Is the direction guaranteed? - actionscript-3

I would like to know the iteration order for the Array, Dictionary and Object types in AS3, for both the for-each and the for-in loops. Also what factors can change the iteration order of these loop type combinations?
For example I presume that using a for-each on an Array type always move from the first element to the last. For-each cannot be used on a Dictionary so how is the order determined using a for-in loop?

As stated in Essential Actionscript 3.0 by Colin Moock, the order of a for each in loop is not guaranteed unless enumerating an XML or XMLList object;
Click here for Colin Moock's words from his book.
There are workarounds as discussed here, but honestly if you need to guarantee the order then just use a regular old for loop and have it iterate (length, numChildren, etc.) number of times.

Do you mean the for (x in y) type of for-each loop? The AS3 specification says that for loops "have the same syntax and semantics as defined in ECMA-262 edition 3 and E4X".
ECMA-262, section 12.6.4 state that "the order of enumeration is defined by the object" - in other words, it will depend on whether you're iterating through a list, a dictionary, an array etc.
I would hope that the documentation for most collections will explicitly state the enumeration order (or that the order isn't defined) but I haven't checked...
EDIT: Unfortunately the specs state that "the mechanics of enumerating the properties [...] is implementation dependent." I can't see anything in the Array docs to specify ordering. It's a bit unsatisfactory, to be honest :(

The order of evaluation changed in AS3.0 Earlier, in AS 1.0 and 2.0, the order of evaluation was based on the order in which the objects were added. Now, in 3.0, all looping maintains array order. Try the snippet:
var a:Array = new Array();
a[ 1 ] = 'first';
a[ 0 ] = 'second';
for (var key:String in a)
trace( key + ': ' + a[ key ] );
Try the above with AS3.0 and AS1.0/2.0

Related

How to emulate an hash table in SQF?

FYI: SQF is a programming language for the computer game series Arma.
The main data types of SQF are documented and the list does not include an hash table (or dictionary).
One way to have a hash table is to create a Game Logic in the mission.sqm (e.g. named logic1), and use setVariable and getVariable on it, e.g.
logic1 setVariable ["variable1", 1];
_a = logic1 getVariable "variable1";
However, this requires an extra array associated with it to track the list of used keys, e.g.
logic1Vars = [];
logic1 setVariable ["variable1", 1];
logic1Vars pushBack "variable1";
logic1 setVariable ["variable1", nil];
logic1Vars = logic1Vars - ["variable1"];
(or is there a way to get the list of variables?)
Another way (that is possible but I haven't tried) is to implement an hash table. That obviously takes an extra effort because implementing a good table is not easy.
But maybe I am missing something: is there an idiomatic way to have an hash table in SQF?
You can use allVariables to retrieve the Number of keys in a Namespace.
To create a Namespace you can use a Logic or a Location or a SimpleObject. See how CBA does it https://github.com/CBATeam/CBA_A3/blob/master/addons/common/fnc_createNamespace.sqf.
Generally a Location or SimpleObject is more Performance friendly than using a GameLogic. You should keep that in Mind.
But what you are probably searching for is the allVariables command which returns all Variables in a Namespace(Hashtable).
You can also use getVariable ARRAY to set a default Value in case the Namespace doesn't contain the Key you want to read.
CBA also has Hashes they behave like a Map. Not like a hashTable (The keys are not hashed) also it's SQF code instead of Engine code so it is slightly slower.
Also (don't have enough reputation to comment)
You don't need all of this:
_vars = _logic getVariable "_VARIABLES";
_vars pushBack "variable1";
_logic setVariable ["_VARIABLES", _vars];
_vars will be a reference to the Array and pushBack will add an element to that Array you are referring to. so pushBack is already modifying _VARIABLES. No need to set it again.
Though this is an old question I'd like to list a new answer that you can now natively create a HashMap in SQF since Arma 3 version 2.01 using the createHashMap command.
One way to create an hash table without having to create it in the mission.sqm is to create it scripting. Specifically, it is possible to write
allHashes = createGroup west; // somewhere once; `west` or `east` does not matter here.
_logic = allHashes createUnit ["LOGIC", [0,0,0], [], 0, "NONE"];
_logicVars = [];
this still requires the list of variables, and thus does not encapsulate the whole hash table in a single object. One way to achieve the hash table logic in a single object is to use
_logic = allHashes createUnit ["LOGIC", [0,0,0], [], 0, "NONE"];
_logic setVariable ["_VARIABLES", []];
and use
_logic setVariable ["variable1", 1];
_vars = _logic getVariable "_VARIABLES";
_vars pushBack "variable1";
_logic setVariable ["_VARIABLES", _vars];
This can be encapsulated in a function, but still needs 4 lines of code to get the whole thing...

AS3: calling a property by name or by reference

I am kinda new to AS and stumbled upon a "funny looking" feature in the documentation:
You can use the Object class to create associative arrays. At its core, an associative array is an instance of the Object class, and each key-value pair is represented by a property and its value. Another reason to declare an associative array using the Object data type is that you can then use an object literal to populate your associative array (but only at the time you declare it). The following example creates an associative array using an object literal, accesses items using both the dot operator and the array access operator, and then adds a new key-value pair by creating a new property:
Copy var myAssocArray:Object = {fname:"John", lname:"Public"};
trace(myAssocArray.fname); // John
trace(myAssocArray["lname"]); // Public
myAssocArray.initial = "Q";
trace(myAssocArray.initial); // Q
from here.
I understand that there are cases where this can be helpful, like this one but with a backround in mostly typesafe languages like Java and C# I am a little bit confused about which access-operator is common practice and why.
Normally I would go with the dot oporator, as it allows me and the compiler to keep track of all given properties and you are save regarding typos.
The code I am looking at right now uses both, with no recognizable pattern, which is even more confusing.
Any input on this? Is one better than the other? Why? When to use which one?
Normally I would go with the dot oporator, as it allows me and the
compiler to keep track of all given properties and you are save
regarding typos.
You are not safe against typos. When you create an Object, any property that you haven't defined/assigned to will just return undefined.
var awd:Object = {}
awd.aaa++ //NaN
awd ['aaa']++ //NaN
The compiler will not catch any attempt to reference a property that hasn't been defined.
I use the [] method almost exclusively because it does everything I would need the . method to do plus more. The biggest advantage for me is that I can access properties via variables.
var awd:Object = {}
var key:String = 'some_key';
awd [key] = 1;
awd.key = 5; //This will literally assign to the 'key' property, not what I want

What's happening when I use for(i in object) in AS3?

To iterate over the properties of an Object in AS3 you can use for(var i:String in object) like this:
Object:
var object:Object = {
thing: 1,
stuff: "hats",
another: new Sprite()
};
Loop:
for(var i:String in object)
{
trace(i + ": " + object[i]);
}
Result:
stuff: hats
thing: 1
another: [object Sprite]
The order in which the properties are selected however seems to vary and never matches anything that I can think of such as alphabetical property name, the order in which they were created, etc. In fact if I try it a few different times in different places, the order is completely different.
Is it possible to access the properties in a given order? What is happening here?
I'm posting this as an answer just to compliment BoltClock's answer with some extra insight by looking directly at the flash player source code. We can actually see the AVM code that specifically provides this functionality and it's written in C++. We can see inside ArrayObject.cpp the following code:
// Iterator support - for in, for each
Atom ArrayObject::nextName(int index)
{
AvmAssert(index > 0);
int denseLength = (int)getDenseLength();
if (index <= denseLength)
{
AvmCore *core = this->core();
return core->intToAtom(index-1);
}
else
{
return ScriptObject::nextName (index - denseLength);
}
}
As you can see when there is a legitimate property (object) to return, it is looked up from the ScriptObject class, specifically the nextName() method. If we look at those methods within ScriptObject.cpp:
Atom ScriptObject::nextName(int index)
{
AvmAssert(traits()->needsHashtable());
AvmAssert(index > 0);
InlineHashtable *ht = getTable();
if (uint32_t(index)-1 >= ht->getCapacity()/2)
return nullStringAtom;
const Atom* atoms = ht->getAtoms();
Atom m = ht->removeDontEnumMask(atoms[(index-1)<<1]);
if (AvmCore::isNullOrUndefined(m))
return nullStringAtom;
return m;
}
We can see that indeed, as people have pointed out here that the VM is using a hash table. However in these functions there is a specific index supplied, which would suggest, at first glance, that there must then be specific ordering.
If you dig deeper (I won't post all the code here) there are a whole slew of methods from different classes involved in the for in/for each functionality and one of them is the method ScriptObject::nextNameIndex() which basically pulls up the whole hash table and just starts providing indices to valid objects within the table and increments the original index supplied in the argument, so long as the next value points to a valid object. If I'm right in my interpretation, this would be the cause behind your random lookup and I don't believe there would be any way here to force a standardized/ordered map in these operations.
Sources
For those of you who might want to get the source code for the open source portion of the flash player, you can grab it from the following mercurial repositories (you can download a snapshop in zip like github so you don't have to install mercurial):
http://hg.mozilla.org/tamarin-central - This is the "stable" or "release" repository
http://hg.mozilla.org/tamarin-redux - This is the development branch. The most recent changes to the AVM will be found here. This includes the support for Android and such. Adobe is still updating and open sourcing these parts of the flash player, so it's good current and official stuff.
While I'm at it, this might be of interest as well: http://code.google.com/p/redtamarin/. It's a branched off (and rather mature) version of the AVM and can be used to write server-side actionscript. Neat stuff and has a ton of information that gives insight into the workings of the AVM so I thought I'd include it too.
This behavior is documented (emphasis mine):
The for..in loop iterates through the properties of an object, or the elements of an array. For example, you can use a for..in loop to iterate through the properties of a generic object (object properties are not kept in any particular order, so properties may appear in a seemingly random order)
How the properties are stored and retrieved appears to be an implementation detail, which isn't covered in the documentation. As ToddBFisher mentions in a comment, though, a data structure commonly used to implement associative arrays is the hash table. It's even mentioned in this page about associative arrays in AS3, and if you inspect the AVM code as shown by Ascension Systems, you'll find exactly such an implementation. As described, there is no notion of order or sorting in typical hash tables.
I don't believe there is a way to access the properties in a specific order unless you store that order somehow.

scala foreach and map initializers

Just seen an interesting possibility to initialize code blocks in Scala for high order functions such as foreach or map:
(1 to 3) map {
val t = 5
i => i * 5
}
(1 to 3) foreach {
val line = Console.readLine
i => println(line)
}
Is this some documented feature or should I avoid such constructs? I could imagine, the "initialization" block comes into the constructor and the closure itself becomes an apply() method?
Thanks Pat for the original Question (http://extrabright.com/blog/2010/07/10/scala-question-regarding-readline)
While the features used are not uncommon, I'll admit is is a fairly odd combination of features. The basic trick is that any block in Scala is an expression, with type the same as the last expression in the block. If that last expression is a function, this means that the block has functional type, and thus can be used as an argument to "map" or "foreach" . What happens in these cases is that when "map" or "foreach" is called, the block is evaluated. The block evaluates to a function ( i=> i*5 in the first case ), and that function is then mapped over the range.
One possible use of this construct is for the block to define mutable variables, and the resulting function mutate the variables each time it is called. The variables will be initialized once, closed over by the function, and their values updated every time the function is called.
For example, here's a somewhat surprising way of calculating the first 6 factorial numbers
(1 to 6) map {
var total = 1
i => {total *= i;total}
}
(BTW, sorry for using factorial as an example. It was either that or fibonacci. Functional
Progamming Guild rules. You gotta problem with that, take it up with the boys down at the hall.)
A less imperative reason to have a block return a function is to define helper functions earlier in the block. For instance, if your second example were instead
(1 to 3) foreach {
def line = Console.readLine
i => println(line)
}
The result would be that three lines were read and echoed once each, while your example had the line read once and echoed three times.
First, the comment of the original blog "Scala Question Regarding readLine" post mention
The “line” is a value and cannot be executed, it is assigned only once from the result of the “Console.readLine” method execution.
It is used less than three times in your closure.
But if you define it as a method, it will be executed three times:
(1 to 3) foreach {
def line = Console.readLine
i => println(line)
}
The blog Scala for Java Refugees Part 6: Getting Over Java has an interesting section on Higher Order function, including:
Scala provides still more flexibility in the syntax for these higher-order function things.
In the iterate invocation, we’re creating an entire anonymous method just to make another call to the println(String) method.
Considering println(String) is itself a method which takes a String and returns Unit, one would think we could compress this down a bit. As it turns out, we can:
iterate(a, println)
By omitting the parentheses and just specifying the method name, we’re telling the Scala compiler that we want to use println as a functional value, passing it to the iterate method.
Thus instead of creating a new method just to handle a single set of calls, we pass in an old method which already does what we want.
This is a pattern commonly seen in C and C++. In fact, the syntax for passing a function as a functional value is precisely the same. Seems that some things never change…

As3 - How to clear an array efficiently?

I've been looking to clear an array in ActionScript 3.
Some method suggest : array = []; (Memory leak?)
Other would say : array.splice(0);
If you have any other, please share.
Which one is the more efficient?
Thank you.
array.length = 0 or array.splice() seems to work best for overall performance.
array.splice(0); will perform faster than array.splice(array.length - 1, 1);
For array with 100 elements (benchmarks in ms, the lower the less time needed):
// best performance (benchmark: 1157)
array.length = 0;
// lower performance (benchmark: 1554)
array = [];
// even lower performance (benchmark: 3592)
array.splice(0);
There is a key difference between array.pop() and array.splice(array.length - 1, 1) which is that pop will return the value of the element. This is great for handy one liners when clearing out an array like:
while(myArray.length > 0){
view.removeChild(myArray.pop());
}
I wonder, why you want to clear the Array in that manner? clearing all references to that very array will make it available for garbage collection. array = [] will do so, if array is the only reference to the array. if it isn't then you maybe shouldn't be emtpying it (?)
also, please note that`Arrays accept Strings as keys. both splice and lenght operate solely on integer keys, so they will have no effect on String keys.
btw.: array.splice(array.length - 1, 1); is equivalent to array.pop();
array.splice(0,array.length);
this has always worked pretty well for me but I haven't had a chance to run it through the profiler yet