There was a fair bit of interest in my post yesterday about implementing Ruby-like iterators in Actionscript, so without further ado here's the source:
/************************
Array methods
************************/
Array.prototype.each = function(block : Function) : Array {
var l = this.length;
for(var i = 0; i < l; i++)
block(this[i]);
return this;
}
Array.prototype.filter = function(block : Function) : Array {
var l = this.length;
var result = [];
for(var i = 0; i < l; i++) {
if (block(this[i]))
result.push(this[i]);
}
return result;
}
Array.prototype.collect = function(block : Function) : Array {
var l = this.length;
var result = [];
for(var i = 0; i < l; i++)
result.push(block(this[i]));
return result;
}
Array.prototype.find = function(block : Function) : Array {
var l = this.length;
for(var i = 0; i < l; i++) {
if (block(this[i]))
return this[i];
}
}
Array.prototype.inject = function(block : Function) : Array {
var l = this.length;
var a = this[0];
for(var i = 1; i < l; i++)
a = block(a, this[i]);
return a;
}
/************************
Object methods
************************/
Object.prototype.each = function(block : Function) : Array {
var l = this.length;
for(var i in this)
if ((typeof this[i]) != "function") block(this[i]);
return this;
}
Object.prototype.filter = function(block : Function) : Array {
var l = this.length;
var result = [];
for(var i in this) {
if ((typeof this[i]) != "function")
if (block(this[i]))
result.push(this[i]);
}
return result;
}
Object.prototype.collect = function(block : Function) : Array {
var l = this.length;
var result = [];
for(var i in this)
if ((typeof this[i]) != "function")
result.push(block(this[i]));
return result;
}
Object.prototype.find = function(block : Function) : Array {
var l = this.length;
for(var i in this) {
if ((typeof this[i]) != "function")
if (block(this[i]))
return this[i];
}
}
Object.prototype.inject = function(block : Function) : Array {
var l = this.length;
var a;
for(var i in this)
if ((typeof this[i]) != "function")
if (a == undefined)
a = this[i];
else
a = block(a, this[i]);
return a;
}
Here's some notes about the purpose of each method:
The original Ruby iterators come in multiple flavours - some replace the original array or object elements rather than create a copy, others return the index/key rather than the value.
There's a bit of extra logic in the object versions of the methods to ignore functions - without this the iterator methods themselves were included in the results. This may not be the desired behaviour - sometimes you want to iterate over functions - but it wouldn't take much tweaking to check the name of the function before skipping it.
I should mention that I also tried adding a times() method to the Number prototype - the idea being that you could write
5.times(function(){...}) to repeat something five times for instance. It actually sort-of worked, but only for numeric variables, e.g. x = 5; x.times(function(){...}) which wasn't that useful. So there you have it - although it doesn't stop there. Taking this callback approach further I was thinking that you could achieve similar outcomes to say ColdFusion custom tags using the function as the tag body. I should also mention that this isn't the first attempt to combine Ruby and Flash - try Googling "Rich Kilmer" (of ActionStep fame) and "Alph".
Cheers,
Robin