Coding

* - *
|

Cleaning Up Ajax

I generally line up on the "Worse is Better" side of things, so it's rare that I'm critical of development tools that appear to be working. As Laszlo has dived into its DHTML port, though, we've been looking at the existing open-source frameworks -- especially at their class models -- to see if there's a standard we can follow, or even a useful bit of code to pick up. I've been a bit disappointed in the way that the various Ajax frameworks treat fundamental object model of the Javascript client that's running in the browser.

the secret art of science

you dive past the still reflective surface of the monitor to that cool, vast world underneath. don't stop falter or pause to run it just hammer the keys. imagine yourself beheaded at the hands of your enemy but your fingers keep moving. your head topples and rolls on the floor but your work doesn't stop; you already moved inside.

Why I like JavaScript, Part f()

First-class functions should be a part of every language. It's funny that this incredibly powerful idea is usually the basis of the computer science curriculum, but it finds little application in modern programming practice.


There's an obvious reason for this: the dominant programming languages (Java and C++) don't have 'em. The lack of them in C++ is excusable; functions-as-a-datatype is a little beyond the close-to-the metal features one expects from C++, but I think their absence in Java is bizarre.


I think there's another, more subtle, reason that you don't see wide adoption of first-class functions in commercial software: the closure idea is hard to grok, and it feels obtuse in languages where you can even treat a plain 'ol int as an object.


I like Javascript's implementation of functions (though once again the syntax is a little off-putting.) There are two ways I can write a function in Javascript. One is like this:

    function highPass( x ){
        return x > 10 ? x : 10;
    }



The other is like this:

    highPass = function( x ){
        return x > 10 ? x : 10;
    }



Either way, these statements are true:

    highPass( 12 ) == 12;
    highPass( 5 )  == 10;

These are in every way equivalent; the name-in-the-declaration syntax is just a special case of assigning a function to a global slot.


One interesting note: if I define an object

    var o = { n : 10 };

And then attach a function to it:

    o.lowPass = function ( x ){
        return x < this.n ? x : this.n;
    }

I can call that function as a method of o. So

    o.lowPass( 12 ) == 10

is true. However, a reference to o.f is not bound. So if I write this:

    var g = o.lowPass;

This statement is true:

    g( 12 ) == undefined;

The reason for this is that there is no 'this' context for the function g. The global g slot is a reference to f, not a reference to f-in-the-context-of-o.


Here's a little Laszlo unit test to make sure I'm not making any of this up:


VIEW PROGRAM



The ECMA-262 spec includes syntax for emulating a bound reference, although you have to remember both the function to call, and the object to call it on.

    //call is unimplemented in Laszlo
    var p = { n : 15 };
    g.call( p , 12 ) == 15;

The call syntax is nice becuase the original function doesn't even have to be a slot in the object p for this to work, but as I noted, "call" is not implemented in the Flash player.


One thing that's funny about "call" is that it is a little backward from the usual OOP paradigm. Usually, you want to ask an object which function to call based on its name, which is the basis of polymorphism. With the call syntax, the programmer retains a reference to a specific function, which may or may not be the one that the given object or class wants to define as this-is-what-I-do-when-you-call "f()".


As a side note, this deficiency in Javascript is the basis for Laszlo's delegates, which are essentially a little datum containing a callback context (the object) and the name of a function to call on it.


Anyway, there is a way to attach data to a function without any of this fancy object business, and I think it's pretty nifty. Although the ECMA spec includes closures, alas the Flash player does not. If the Flash player supported closures, you could write a function generator this way:

    //this won't work in Laszlo
    function makeFilter ( low, high ){
        return function ( x ){
            return x < low ? low : ( x > high  ? high : x );
        }
    }

This relies on the magic binding of the anonymous function created inside the makeFilter to the scope in which it was created. Admittedly, if you've written an interpreter, this isn't quite as arbitrary as it seems, but if you're just an everyday programmer, it doesn't make a ton of sense, especially given the way that you can just add properties to just about anything in Javascript. Also, closures have the problem that the data which is bound to the function is implicit; there's no easy way to poke at the values for high and low once you've generated the closure.


Javascript offers a nifty alternative, wrapped (as usual) in bad syntax. Within the context of a function, the function itself can be referenced by using the callee property of the implicit arguments array. Here's a rewrite that uses arguments.callee:

    function makeFilter ( low, high ){
        var f = function ( x ){
            var low = arguments.callee.low;
            var high = arguments.callee.high;
            return x < low ? low : ( x > high  ? high : x );
        }
        f.low = low;
        f.high = high;
        return f;
    }

This has the additional advantage that I can later inspect and/or change the values for low and high. Here's a little program that puts this to use filtering an array of random numbers.


I call the return type of makeFilter a pseudo-closure. If the Flash player followed the ECMA spec, I probably wouldn't have adopted this idiom, but now that I have, I prefer it to closures. I think it's easier to understand and maintain.


Here's a little program that adds a filter capability to arrays and then uses pseudo-closures to take advantage of it.


<canvas height="200">
    <script>
        <![CDATA[
        Array.prototype.filter = function ( f ){
            for ( var i = 0; i < this.length; i++ )
                this[ i ] = f( this[ i ] );
        }
        ]]>
    </script>
    <method name="initArray">
        <![CDATA[
        var a = [];
        for ( var i = 0; i < 20; i++ )
            a[ i ] = Math.floor( Math.random() * 100 );
        return a;
        ]]>
    </method>
    <method name="makeFilter" args="low, high">
        <![CDATA[
        var f = function ( x ){
            var low = arguments.callee.low;
            var high = arguments.callee.high;
            return x < low ? low : ( x > high ? high : x );
        }
        f.low = Number( low );
        f.high = Number( high );
        return f;
        ]]>
    </method>

    <attribute name="anArray" value="$once{ canvas.initArray() }"/>
    <simplelayout spacing="10"/>
    <text text="${canvas.anArray}" width="400"/>
    <view>
        <text y="2">Low: </text> <edittext id="lo" x="40" width="40" text="20"/>
    </view>
    <view>
        <text y="2">High:</text> <edittext id="hi" x="40" width="40" text="80"/>
    </view>
    <button>Add filter
        <method event="onclick">
            var f = canvas.makeFilter( lo.getText() , hi.getText() );
            canvas.anArray.filter( f );
            //make the text field update
            canvas.onanArray.sendEvent( );
        </method>
    </button>
</canvas>

(EDIT PROGRAM)

Class Warfare

I'm as much of an OOP adherent as the next person. You say to me: "encapsulation, polymorphism and inheritance" and to you I say, "right on." But I find it interesting and somewhat disappointing that the notion of "object-oriented" is conflated with the notion of "class", which I consider an implementation detail.

I'll get back to some of those implementation details in a second, but let me lay out the two reasons why I don't like classes.

First, classes are too big to be truly atomic. If you consider the spectrum between a single function or data type, and the whole of a program, classes land very near to the latter. Every working programmer knows this problem, and there are any number of informal and formal strategies for dealing with it. Aspects recognize this problem, but I find the Aspect notion complicated, too tied to the particulars of the Java language (even though it's not supposed to be,) and in practice, only useful for a limited number of applications.

The second problem with classes is that they don't allow very well for the fact that objects change over time. If I take a UI element in my program and drag it from one window to another, it's likely that some fundamental aspects of what it is will change at the end of that operation. As a class designer, though, I have two unappealing choices when specifying the class. One is to write a single class that encompasses all the possible behvior that the object could have (along with the requisite switch statements.)

The other possibility is to write several classes to express the various possibilities for its end state, and then to write the n! constructors for those classes so that I can create an instance of any once class from an instance of any other. I could try to solve some of this problem by giving all the possible end-states a common superclass, but then I have to choose either only to represent the particular object as a class hierarchy, or to represent the abstract notions of 'draggable', 'inwindowA', and 'inwindowB' as classes, but not both. No matter what else happens, I'm going to have to destroy and re-create the object, which is likely to be slow.

Multiple inheritance was supposed to solve some of this problem, but it has become something of a dirty word in modern programming with the advent of Java and C#. This is not (in my opinion) because multiple inheritance wasn't a useful concept, but because it was too hard to use and because it leads to all sorts of unexpected behaviors and errors. This is my thesis statement, tucked into in aside: I'm basically saying that classes don't really do a good job of representing abstract things at all -- they ultimately always must represent instances -- which is antithetical to the highest aspirations of OOP.

Now it may seem strange to criticize classes and endorse OOP, but in fact the two are almost completely separate. Classes make it easier to write compilers, and (arguably) easier to write interpreters, but otherwise, they're pretty 20th century. Consider this snippet of Javascript:

    function f (){ Debug.write( "My name is" + this.name ) };
    var o = { name : "Object o" , sayName: f };
    o.sayName();

That's encapsulation. Here's polymorphism:

    function g (){ Debug.write( "I don't have a name." )};
    var n = { sayName: g };
    list = [ o , n ];
    for ( var slots in list )
        list[ slots ].sayName();

Note that we've done all this without creating a template for these things. The call-by-name semantics of Javascript, combined with its first-class functions, make this possible.

Now inheritance is trickier. I've written about __proto__ before, and this is where it comes into play. I could add a method to both o and n by giving them the same __proto__ and then manipulating that.

    var sup = {};
    sup.enumerate = function {
        for ( var keys in this ){
            Debug.write( keys, this[ keys ] );
        }
    }
    o.__proto__ = sup;
    n.__proto__ = sup;
    o.enumerate();
    n.enumerate();

Note that there are some important differences between __proto__ and classes. The first is that __proto__ is a post-hoc operation. I can set and change my __proto__ well after I've been created. Second, my __proto__ can be an instance of an Object. This gives me several powerful options, like transforming a set of objects by calling a function on their __proto__, and it gives me a fast way to clone an existing object. It also lets me do exotic stuff, like configure a class at runtime.

This is a side note, but it's worth taking a second to think about the fact that runtime-interpreted languages have a curious property. Terse syntactic constructs tend to run faster than longer ones, because in general, most of the time spent running a program is in reading and dispatching the bytecodes. This essentially means that the more power in the constructs that are built into the runtime, the faster its programs can run.

Anyway, Javascript isn't perfect. __proto__ solves problem #2 above (the fixed-ness of classes), but not problem #1 (the bigness of classes.) My big complaint with __proto__ is that it is a single slot. This makes multiple inheritance hard to implement and much less efficient than it could be. What I really want to be able to do is to define a set of very small atoms which can by combined in arbitrary ways. What follows is not real syntax in any language, but hopefully you'll get the idea:

    Draws = {};
    Draws.draw = function (){ ... }
    Draws.invert = function (){ .... draw() .... };
    ...

    LoadsMedia = {};
    LoadsMedia.load = function ( url ){ ... };
    LoadsMedia.draw = funtion () { ...super.draw()... };

This is very similar to the inheritance pattern, but with an important difference, because I could do this:

    View = new LoadsMedia,Draws;
    aview = new View;

Here's another thing I could do

    Minimized = {};
    Minimized.draw = function(){ /*make smaller*/ ... super.draw() .... };

    aview.pushProto( Minimized );
    aview.draw();

I think you can imagine what I think pushProto should do.

The big ? (read "question mark") in the above code revolves around the exact semantics of "super." I have some ideas about that, but I think I've gone on long enough for this particular installment. Hopefully, I'll get around to treating that at a later date.

I've been calling these little objects that represent parts of classes "transformers." People laugh at me, but I'm used to it. As usual, I've written some code that shows what you get from Javascript.

VIEW/EDIT PROGRAM

<canvas debug="true" height="250">
    <debug height="240"/>
    <script>
        function f (){ Debug.write( "My name is" + this.name ) };
        var o = { name : "Object o" , sayName: f };
        o.sayName();
        Debug.write( "---------" );

        function g (){ Debug.write( "I don't have a name." )};
        var n = { sayName: g };
        list = [ o , n ];
        for ( var slots in list )
            list[ slots ].sayName();
        Debug.write( "---------" );

        var sup = {};
        sup.enumerate = function (){
            this.sayName();
            for ( var keys in this ){
                Debug.write( "   " +keys+ ":", this[ keys ] );
            }
        }
        o.__proto__ = sup;
        n.__proto__ = sup;
        o.enumerate();
        n.enumerate();
    </script>

</canvas>

Why I like JavaScript (Part I)

I really like a lot of things about JavaScript. With the exception of a few bizarre syntactic constructs, I think it's the most sensible thing going. Of course, I have a loose-typing, runtime bias so you can send me your flames about how that proves I'm a drooling, barely computer-literate script kiddie, but I promise that I won't read them.

Anyway, here's one thing that I find particularly nifty about JavaScript. It's a concept that I've seen referred to as "protection."

Given an object o which has slot n set to 6

    var o = { n : 6 };

I can create another object, oprime, which uses o as its __proto__. (Remember I mentioned the bizarre syntactic constructs? Well this is an example of bad syntax for a useful feature.)

    var oprime = { __proto__ : o };

If an object is your __proto__, that means that when the runtime goes to look for the value of one of your slots, if you haven't defined it, then the runtime looks for that slot in your __proto__. If it's not there, then the runtime looks in that object's __proto__, and so on. The object Object (ok, there's another bizarre syntactic construct -- every object in a JavaScript ultimately descends from the object named... "Object". Bad name, but decent idea) is at the root of every __proto__ chain.

Anyway, this is the essence of inheritance, but boiled down into something very pure and simple. So given the statements above, the expression:

    oprime.n == 6

is true. Also, I can affect the value of oprime's n slot by changing the value of o's n slot. So this:

    o.n++;
    oprime.n == 7;

is also true, even though oprime has no slots, and technically the runtime hasn't even had to allocate any memory for it yet. (In fact, the runtime probably has already allocated a bucket for its slots, and the global slot oprime is a pointer to that bucket.)

Now, consider what happens when I write this:

    oprime.n++;
    oprime.n == 8;

(The last statement is true by the way.) What happens here? Well, I think this is pretty nifty. The runtime gets the value for the n slot, which is 7, and then sets it on oprime, so now oprime has its own n slot, which masks the value of o's n slot. We could prove this a couple of ways, but the easiest is to simply delete the slot in oprime.

    delete oprime.n;
    oprime.n == 7;

Pleasant, no? Also pleasant is the fact I won't affect o by calling stuff on oprime. So for instance, if I try to delete n again:

    delete oprime.n;
    oprime.n == 7;

The last statement is still true.

I wrote a little unit test using Laszlo to prove all of this. Feel free to play with the source.

EDIT PROGRAM

<canvas>
    <include href="lzunit"/>
    <TestSuite>
        <TestCase>
            <method name="test">
                var o = { n : 6 };
                var oprime = { __proto__ : o };
                AssertEquals( 6 , oprime.n );
                o.n++;
                AssertEquals( 7 , oprime.n );
                oprime.n++;
                AssertEquals( 8 , oprime.n );
                delete oprime.n;
                AssertEquals( 7 , oprime.n );
                delete oprime.n;
                AssertEquals( 7 , oprime.n );
            </method>
        </TestCase>
    </TestSuite>
</canvas>
|
* * *
Syndicate content