views:

562

answers:

2

I'd really like to be able to make Flash's array access syntax 'wrap' over the array's bounds.

Lengthy explanation -

var array:Array = ['a','b','c','d','e','f'];

To keep things simple, the first index is 0, and its value is the first letter, 'a'. To get that value, we'd do this -

array[0]; // returns 'a'

As long as the index you're using to access the array is between 0 and array.length (6 in our example,) everything works fine - but if you use an index outside of those bounds, you're shut down.

array[-3];
array[9]; // both return 'undefined'

Sometimes that's a good thing - sometimes you expect that to happen, and you're fine with it. Other times, you find yourself wishing (or at least I find myself wishing) that it'd behave a bit more like this -

array[-3];
array[9]; // both return 'd'

(e.g. a photo gallery that jumps back to the beginning when you click 'next' on the last photo)

There's a little chunk of code I use over and over for this sort of thing, but it's always to alter the index before passing it into the array:

var index = -3;
while(index < 0){index += array.length}
array[index % array.length]; // returns 'd'

... and that's fine, but what I really want to do is extend the Array object itself so that it'll automatically 'wrap' index values that go out of bounds.

TL;DR - Is index-wrapping possible by extending Flash AS3's Array object?

A: 

Not really. You can not override the [] operator. However you can extend the Array and add a function that will apply the code snippet. That being said I am not sure why you really want this functionality. A circular linked list would be a more suitable data structure.

Allan
A linked list doesn't sound like the best option if you want random access.
Juan Pablo Califano
I was just thinking that rather then always adjusting the index value _before_ feeding it into the Array, it might be interesting to make the Array simply be able to _accept_ the index in that format.
matt lohkamp
@Juan - well from Matt's description it sounded like a carousel photo gallery :)
Allan
+4  A: 

Check out the Proxy class: http://livedocs.adobe.com/flex/2/langref/flash/utils/Proxy.html.

I haven't used it myself but it seems it could do the job. I modified the sample code in the docs and it works the way you want. I haven't thoroughly tested it, though, and you might want to do it. Personally, I would not extend Array and just make a simple class with 2 methods for adding/retrieving, since the proxy idea seems a bit involved to me. But that's me.

package
{
    import flash.utils.Proxy;
    import flash.utils.flash_proxy;

    dynamic class ProxyArray extends Proxy {
        private var _item:Array;

        public function ProxyArray() {
            _item = new Array();
        }

        override flash_proxy function callProperty(methodName:*, ... args):* {
            var res:*;
            res = _item[methodName].apply(_item, args);
            return res;
        }

        override flash_proxy function getProperty(name:*):* {
            if(!isNaN(name)) {
                var index:int = name;
                while(index < 0) {
                    index += this.length;

                }
                return _item[index % this.length];
            }


            return _item[name];
        }

        override flash_proxy function setProperty(name:*, value:*):void {
            _item[name] = value;
        }
    }
}

Use:

        var a:ProxyArray = new ProxyArray();
        // you can't use this syntax ['a','b','c'], since it would return an Array object
        a.push("a");
        a.push("b");
        a.push("c");
        a.push("d");
        a.push("e");
        a.push("f");

        trace(a[-3]);
        trace(a[9]); 
Juan Pablo Califano
+1. Absolutely the right answer as far as I am concerned. The +1 is for using dynamic class with flash_proxy.
sberry2A
Huh - fascinating! I'll have to fool around with this a little - maybe you're right, it might be easier just to make a sort of wrapper-class that layers the 'wrap' functionality on top of the array, but yeah... I'll give it a try!
matt lohkamp
cool, yeah, got this slotted into the project I was messing around with, does exactly what I wanted. I can see I'm going to have to spend some time playing with the Proxy class, I haven't had any occasion to look at it before... thanks!
matt lohkamp
... although it looks like for(i in array){...} syntax doesn't work: "Error: Error #2105: The Proxy class does not implement nextNameIndex. It must be overridden by a subclass."
matt lohkamp
Well, you have to override that method if you want to use for and for each on your collection. It's certainly a good use case, IMO. You can find sample implementations in the docs: http://livedocs.adobe.com/flex/2/langref/flash/utils/Proxy.html#nextNameIndex()http://livedocs.adobe.com/flex/2/langref/flash/utils/Proxy.html#nextValue()http://livedocs.adobe.com/flex/2/langref/flash/utils/Proxy.html#nextValue()
Juan Pablo Califano