Posts about actionscript

Vector for ActionScript3

I just learned about Vector, it's a typed Array for Actionscript 3, like generics in Java or C#. However, in Actionscript 3, Vector is a one-off: it's the only class that uses the generics syntax, and developers cannot use generics in their own classes. Nevertheless, Vector gives a type-safe alternative to Array and promises big performance gains. Given that it can also give the type of the containing elements at runtime, I can use it now to drive JSON deserialization into objects too.
Posted by Toby 5 months ago about actionscript, flex and programming (0 comments)

Modifying Core Types in ActionScript 3 Using the Prototype Object

ActionScript 3 has a Javascript lineage. It was essentially a fork of Ecmascript. Plus, the Adobe team has worked hard on making the language a proper superset of the Ecmascript specification. This is why although ActionScript 3 was a major architechtural change from 2, and as a result became much more like Java than Javascript, it still has support for the prototype object

When I learned about the prototype object, it was a fresh air from traditional class-based OOP. Studying cool libraries like prototype.js made me realize that the prototype model makes javascript far more flexible than some other strictly class-based OO languages.

One of the cool things you can do with the prototype object in javascript is modify the core classes of the language, like Array, String, and Date. You can do this in ActionScript 3 too, for it conforms to Ecmascript 4. For example, let's say you want to write the collect function for arrays a la ruby. You would do:
Array.prototype.collect = function(f){
  var ret = [];
  for each(var it in this) ret.push(f(it));
  return ret;
}
There you see me using the nice  for each syntax. But, this is going to break the behavior of the array, because now the collect function is going to show up in the enumeration in the for each loops. We don't want that, so to fix that we are going to set the collect attribute of Array.prototype to not be enumerable:
Array.prototype.setPropertyIsEnumerable('collect', false);
This allows you to write the following code:
[1,2,3].collect(function(i){ return i * 2; });
// result would be [2,4,6]
It's kinda tedious to have to setPropertyIsEnumerable for every time we add a function to an existing type, so I wrote a convience function:
function addMethodsTo(cls:Class, methods){
    for (var name:String in methods){
        cls.prototype[name] = methods[name];
        cls.prototype.setPropertyIsEnumerable(name, false);
    }
}
Which you can use like so:
addMethodsTo(Array, {
    collect: function(f){
        var ret = [];
        for each(var it in this) ret.push(f(it));
        return ret;
    },
    anotherMethod: function(){
        ...
    },
    ...
});
This is sort of like the style prototype.js uses for extending/creating classes.

A Word of Caution
Before you consider going further with this, I must advice you to think twice before using this technique(however, I hope you do decide to use it afterwards ;). There are several caveats:
  1. The prototype-based style is a second-class citizen in the world of ActionScript 3 and Flex. The Adobe team as well as the community seem to be much more committed to the class-based approach. I will describe some of the rough edges below.
  2. You will give up compile time type checking for the portions of your code that use this style.
  3. Prototype inheritence is handled by a completely different mechanism than class-based inheritence in the Flash VM and is not as performant.

Where to put this Code?
You saw the code example above, but, where do you put it? Since I decided to use a helper function(addMethodsTo), the code cannot be directly pasted inside the class scope of a class unless the addMethodsTo function is declared to be static(you can only make a method call directly inside class scope if it is a class method). As, a general solution, I'd rather the code be portable. So it should be includable in both class and function scope, and also, I'd like it not to pollute any namespaces.

My current solution is to put this bit of code inside an anonymous function which immediately gets executed:
// contents of includes/Array.as
(function(){
    include 'addMethodsTo.as';
    addMethodsTo(Array, {
        collect: function(f){
            var ret = [];
            for each(var it in this) ret.push(f(it));
            return ret;
        }
    });
})();
The addMethodTo function is pulled into a separate file to be easily includable else where.
So, with this, I would do the following to include this Array functionality:
include 'includes/Array.as';
Head over to Github for the complete structure of the files.

These methods are added during runtime - at exactly the time the above line of included code is executed, and not a moment before. I like to do the include at the top level of the application, this way the entire program has immediate access to the new methods. Oh, and when I said entire program, I do mean the entire program - not just the files that happen to include the file. Well, this is good and bad. This means if you create components that use the array extensions you've created without explicitly including it(you've included it at the entry point of your program), then you have created an invisible dependency. If you try to take the component and use it in a different project without the array extensions, it will not work. Of course, you could also make the dependency explicit by including the file everywhere you are using them, but 1) that's kinda tedious/repetitious, and 2) there's nothing enforcing you to do this.

Pitfalls and Gotchas
As I mentioned, the prototype-based programming style is a second-class citizen in the ActionScript 3 world, and so, its use is not particularly well supported. First of all, the compiler does not recognize any of the methods added via the prototype mechanism, and thus cannot perform static type checking on them. But what is funny is the way the compiler copes with this - it depends...on the type in question. For Arrays, the compiler simply allows all method calls - you can call any method on an array, even if it doesn't exist, the compiler won't complain. So, for a call like:
[1, 2, 3].collect(...);
The compiler won't even say a word. But for Dates, it gives a warning message. This:
new Date().format()
would trigger this warning:
Warning: format is not a recognized method of the dynamic class Date.
But, for strings, it's a different story still:
'one, two, three'.csv2Array()
compiler says:
Error: Call to a possibly undefined method csv2Array through a 
    reference with static type String.
And the same thing with numbers:
(2).minutes().ago()
compiler says:
Error: Call to a possibly undefined method minutes through a 
    reference with static type int.
The work around for strings and numbers is to upcast it to an Object:
Object('one, two, three').csv2Array();
Object(2).minutes().ago();
or if you just have an untyped variable, it'll work just fine:
var x = 2;
x.minutes().ago();
See the full code example here, and the demo here.

What about runtime error handling? So let's see what happens if you don't include the extensions and run the code. When I took out the array extension methods, the runtime dutifully throw me the:
TypeError: Error #1006: collect is not a function.
This is good, just what I would expect. For Date, it works the same way. Now let's try taking out the string extensions:
TypeError: Error #1006: value is not a function.
Uhh, what? Not really sure what you mean. And as you would expect, it works like this for Number as well.

I have also seen cases where the runtime simply completely muffles an error when there's an undefined method being tried as someone documented here. But I am not able to reproduce this just now. Also on another note, the error stacktrace from the flash player(debug version) is not very helpful because although it gives the call stack, there are no line numbers. I am sure that you'd get a better experience using Flex Builder, however.

I think that about wraps it up. Although extending core types is fun, powerful, and elegent, it's also full of holes and flying scissors everywhere. Are you ready to jump into this brave new world?

A message to the Adobe Flex/ActionScript team: I implore you to put more effort into the prototype-based side of the language. It allows for many possibilities which its class-based counterpart cannot offer. I don't dislike the class-based approach. I think the two each have their own strengths and weakness. Which is why I love this hybrid aspect of ActionScript 3 which allows me to use either style in the same environment. I believe that if the prototype-based aspect of ActionScript were to improve and get more exposure, it would not only become a better language, but also a more wide spread language.
Posted by Toby 10 months ago about actionscript, flex, javascript, programming and prototype (10 comments)

Different Ways of Including Functions in ActionScript

This is another example of something that would have been a blog post creeping over to SO.
Posted by Toby 10 months ago about actionscript, flex and programming (0 comments)

Property Binding in Flex

I have been working more with Flex now, and I have to say: the data binding features(covered here) in Flex is beautiful. It's light years ahead of anything I've ever seen before. 

Example 1: You want a Text element to show the full name of current selected state from a drop down: 
    <List id="stateList" labelField="abrv">
        <ArrayCollection>
            <Object abrv="NJ" full="New Jersey"/>
            <Object abrv="MA" full="Massachusetts"/>
            <Object abrv="NY" full="New York"/>
            <Object abrv="NC" full="North Carolina"/>
        </ArrayCollection>
    </List>
    <Text text="{stateList.selectedItem.full}"/>
The code in the curly braces is some ActionScript code, but it doesn't just get executed once, oh no, you can look at it as an invariant, i.e. the content of the said text element will always contain the value expressed by stateList.selectedItem.full. Therefore, when you change the selection of stateList, the text element will immediately change with it. Here's the code and live demo for example 1.

Example 2: Let's try binding to a custom variable rather than to another control. We first make our counter variable public and bindable:
    <Script>
    [Bindable]
    public var counter:int = 0;
Then, we can bind a text control to it:
    <Text text="{counter}"/>
Next, we can periodically increment the variable like so:
        setInterval(function(){
            counter++;
        }, 1000);
And you will see the number in the text display count up: the display in the text element is syncronized with the actually value of counter. The code and live demo for example 2.

Next, let's try creating our own properties. ActionScript has support for Java-style OOP(as supposed to Javascript style), but, more interestingly, it's got direct support for properties. Add direct support of property change event bindings, and it's a beautiful thing. 
Example 3: You have a Page object that manages the details of paginating a set of data, and you need some controls to navigate between the pages as well as display what page you are on. You create a Page object:
    class Page extends EventDispatcher{
        public var number:int;
        public var size:int;
        public var total:int;
        ...
    }
A page has a page number, a page size, and the total size of the data set(used to tell whether a page exists). I instantiate a Page object:
    <Script>
    [Bindable]
    public var currentPage:Page = new Page(0, 10, 100);
    </Script>
I need a label that tells me the range of results currently being viewed:
    <Label text="{currentPage.from} to {currentPage.to}"/>
Here, the label binds to 2 properties: from and to. Let's implement these properties:
    class Page extends EventDispatcher{
        ...
        [Bindable]
        public function get from():int{
            return number * size + 1;
        }
        [Bindable]
        public function get to():int{
            return (number + 1) * size;
        }
        ...
    }
Notice the get syntax: this in ActionScript turns the function into a getter for a property of the same name. Also notice that I made these properties bindable.
Next, I need the previous and next buttons. I choose to sandwich the label in between them:
    <Button label="Previous" click="currentPage.prev()"/>
    <Label text="{currentPage.from} to {currentPage.to}"/>
    <Button label="Next" click="currentPage.next()"/>
Clicking on Previous will call the prev method and clicking on Next will call the next method. Simple. Here is the code:
        public function next(){
            number++;
        }
        
        public function prev(){
            number--;
        }
Compiled it, but it doesn't work. Clicking on Previous and Next does no change the display on the label at all. Oh! We need to fire the events! To fire a property change event, you'd do something like:
                this.dispatchEvent(new PropertyChangeEvent(
                    "propertyChange", true, true, 
                    PropertyChangeEventKind.UPDATE,
                    propertyName, null, null, this));
In our case, we are going to fire the change events for both from and to, because both of those must change after you flip a page. So we fire the changes:
        private function fireChanges(){
            var toFire = ['from', 'to'];
            for (var i = 0; i < toFire.length; i++)
                this.dispatchEvent(new PropertyChangeEvent(
                    "propertyChange", true, true, 
                    PropertyChangeEventKind.UPDATE,
                    toFire[i], null, null, this));
        }
        public function next(){
            number++;
            fireChanges();
        }
        public function prev(){
            number--;
            fireChanges();
        }
Ok, but I would like to disable the Previous or Next button when we are at the begining or the end of the dataset. No problem! We create a couple more bindable properties: hasNext and hasPrev:
        [Bindable]
        public function get hasNext():Boolean{
            return to < total;
        }
        [Bindable]
        public function get hasPrev():Boolean{
            return number > 0;
        }
Bind the buttons' enabled property to them:
    <Button label="Previous" click="currentPage.prev()" 
        enabled="{currentPage.hasPrev}"/>
    <Label text="{currentPage.from} to {currentPage.to}"/>
    <Button label="Next" click="currentPage.next()"
        enabled="{currentPage.hasNext}"/>
Make sure to fire the change events for them too when you are flipping pages(add them to toFire in the implementation of fireChanges) and we are done. The code: ex3.mxmlPage.as and live demo for example 3.

The end result of this is that you have very well separated MVC code. There isn't any code whose sole purpose is to sync the display like you get with jQuery code, for example. The code to do this is very minimal and naturally readable.

All code examples can be found here on Github.

Btw, I should mention that, the code inside of the curly braces does not allow any arbitrary ActionScript. There is some amount of flexibility, but not a lot. You can read more here.
Posted by Toby about 1 year ago about actionscript, flex and programming (0 comments)