Posts about prototype

Typed Deserialization with JSON

JSON is nice, but if you use it extensively, you go against the OO style of object modeling, which says that behaviors should be attached to objects themselves. Even if you are not an OO bigot, the OO way is sometimes just far more convenient and structures your code better, IMHO. Given my past work with JYaml, it can't be that hard to read in some JSON and directly deserialize it into a typed object can it?

Say you have a Person type:
function Person(name){
    this.name = name
}
Person.prototype.sayHi = function(){
    return "Hi! I am " + this.name
}
You create an instance called tommy:
> tommy = new Person('Tommy')
> tommy.sayHi()
Hi! I am Tommy
With a little magic from a toJson function that I whipped up:
> tommyJson = toJson(tommy)
> tommyJson
{__proto__: Person.prototype, name: "Tommy"}
tommyJson is now a string representation of tommy. You can see that it sets the special __proto__ link to Person.prototype, which will do its magic when it's deserialized. Now let's deserialize it back:
> tommyCopy = fromJson(tommyJson)
> tommyCopy.sayHi()
Hi! I am Tommy
> tommyCopy.constructor
function Person(name){
    this.name = name;
}
> tommyCopy === tommy
false
As you can see, the deserialized object tommyCopy is not just a plain object literal, but has all of the behaviors of Person.

The code for toJson and fromJson is so small I don't even bother putting it on github, so I'll just post it here(You may need ecma5array if you want to run it on a sucky browser):
function toJson(obj){
    function keys(o){
        var ret = []
        for (var key in o){
            var val = o[key]
            if (o.hasOwnProperty(key)) // exclude attributes in the parent
                ret.push(key)
        }
        return ret
    }
    function quote(str){
        return '"' + str + '"'
    }
    if (obj === null || obj === undefined)
        return String(obj)
    else if (obj.constructor === String)
        return quote(obj)
    else if (obj.constructor === Array)
        return '[' + obj.map(toJson).join(', ') + ']'
    else if (obj.constructor === Object)
        return '{' + keys(obj).map(function(key){return key + ': ' + toJson(obj[key])}).join(', ') + '}'
    else if (obj.constructor && obj.constructor.name)
        return '{' + ['__proto__: ' + obj.constructor.name + '.prototype'].concat(
            keys(obj).map(function(key){return key + ': ' + toJson(obj[key])})).join(', ') + '}'
    else
        return String(obj)
}
function fromJson(str){
    return eval('(' + str + ')')
}

Posted by Toby 5 months ago about javascript, programming and prototype (0 comments)

Prototype Inheritence in Python

One of Toby's favorite pastimes is to take concepts from one language and realize it in another. In this episode: Toby implements Javascript-style prototype inheritence in Python.

One thing that is super cool about Javascript is the fact that objects are just maps. Not only can you add attributes dynamically at any point, you can also add methods dynamically. In Python, you can add methods dynamically, but normally you'd have to add it into the class. But there are cases when you don't want to bother making a class. This inspired me to see how far I can go in making Python behave more like Javascript.

Introducing prototype.py
prototype.py lets you write code in Python with Javascript-style prototype inheritence semantics. If you are not familiar with prototype inheritence, just read on for now. I will link to some resources at the end. Now, let's see how to use this bad boy. First you import the module:
>>> from prototype import *
To create a constructor(we don't really have classes anymore), you write a function with the @constructor decorator:
>>> @constructor
... def Person(this, first, last):
...   this.firstName = first
...   this.lastName = last
...
>>> Person
<constructor 'Person'>
I am going to use this rather than self and camelCase rather than under_scores for prototype-style code, because, well...Dorothy, we are not in Kansas anymore.

Now you can do:
>>> bird = Person('Charlie', 'Parker')
>>> bird.firstName
'Charlie'
>>> bird.lastName
'Parker'
You can add attributes to the object just like in normal Python. But unlike in normal Python, which would raise an AttributeError when trying to access non-existent attributes, in prototype-land it merely returns None:
>>> print bird.age
None
You can dynamically add a method to the instance just by tagging on a function:
>>> def sing(this):
...   print '%s sings!!' % this.lastName
...
>>> bird.sing = sing
>>> bird.sing()
Parker sings!!
This affects only the bird instance. If you want the method to be added to all instances of Person however, you can add it to the prototype of Person.
>>> Person.prototype.sing = sing
>>> monk = Person('Thelonious', 'Monk')
>>> monk.sing()
Monk sings!!
This works because Person.prototype is the prototype of the monk instance. In code, this means:
>>> monk.__proto__ == Person.prototype
True
When the sing attribute is not found on the monk instance itself, it will follow the __proto__ reference and look it up in its prototype, which is also referred to as its parent. We can manipulate the parent link:
>>> monkJr = Person('T.S.', 'Monk')
>>> monkJr.__proto__ = monk
so that now monkJr inherits all of monk's attributes:
>>> monk.hair = 'black and curly'
>>> monkJr.hair
'black and curly'
The following are some other properties demonstrating the prototype inheritence model:
>>> assert monkJr.constructor == monk.constructor == Person
>>> assert Object.prototype.constructor == Object
>>> assert Person.prototype.constructor == Person
>>> assert Person.prototype.__proto__ == Object.prototype
If this seems confusing, remember that in prototype-land, there are two kinds of things: constructors and instances. The prototype of a constructor is nothing more than an instance of the type that the constructor represents. A new instance returned from calling a constructor will have its parent set to the prototype of the constructor.

Things You Can't Do in Javascript, i.e. the 1+1>2 Effect
Python is a more powerful and flexible language than Javascript, so, why am I dumbbing it down to Javascript's level? To show that I am not trying to do that at all, let me point out that there are at least a couple of really cool things you can do with prototype.py that you can't with Javascript, simply due to the fact that it is in Python.

The first thing is properties. With prototype.py, you can add properties to objects like so:
>>> def getName(this):
...   return '%s %s' % (this.firstName, this.lastName)
...
>>> Person.prototype.name = property(getName)
>>> bird.name
'Charlie Parker'
You can also specify setters and deleters in the way you'd expect:
>>> def setName(this, name):
...   first, last = name.split(' ')
...   this.firstName = first
...   this.lastName = last
...
>>> def deleteName(this):
...   del this.firstName
...   del this.lastName
...
>>> Person.prototype.name = property(getName, setName, deleteName)
>>> bird.name = 'Dizzy Gillespie'
>>> bird.name
'Dizzy Gillespie'
>>> del bird.name
>>> bird.name
'None None'

The second thing is named parameters, keyword parameters and optional parameters. Let's just do an example with keyword parameters. Let's say I just wanted a way to easily create ad-hoc objects as key-value pairs, I could write:
>>> @constructor
... def Data(this, **kwargs):
...   for key in kwargs.keys():
...     setattr(this, key, kwargs[key])
...
Which lets me write:
>>> project = Data(project='prototype.py', language='python')
But, I could also define methods and properties in this way:
>>> file = Data(fileName='prototype.py', fileExt=property(getExt)
                    read=read, write=write)
Sweet!

A Note About the Implementation
The implementation of prototype.py is only about 60 lines of Python at time of writing, would have gone down to 40 without property support. The code can be found here. 

A big discovery that enabled me to do this was the new module. It allowed me to take a function and make it into an instance method by binding it to an object:
method = new.instancemethod(function, object)

Another note is that I made the design decision that for methods, I chose to store the unbound function rather than the bound method in the __dict__ of the object. I would then bind the function on the fly when it's asked for. This made it very easily to inherit methods because you don't have to worry that the method is really bound to the parent rather than the instance in question.

Further Reading About Prototype Inheritence
If you want to learn more about prototype inheritence, try:
Posted by Toby 9 months ago about javascript, programming, prototype and python (2 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)

Making justtodolist work for chrome and safari

Since Chrome is so great, I wanted to use it for all my browser needs. But the apps I've been working on myself have not been targeted for WebKit - the rendering engine used by chrome, and also used my Safari. This is mostly due to laziness on my part - having to handle two browsers at a time is chaos enough. But Safari compatibility is on my todo list for more than one of my projects, and chrome is a good push for this cause. And so I went in today and made just todo list. compatible with Chrome and Safari. The differences I encountered were:
  1. This is really prototype specific - prototype adds an empty underscore parameter for all Ajax request for WebKit browsers. Because apparently, Safari errors out when you try to post with an empty body on XHR calls. And, who knows, this might already be fixed in WebKit. I happened to have code that was not handling this fact on the server side. This was no biggy.
  2. This is an error on my part really, but I had a form with a text input inside. But also registered for the key events on the text input so that when enter is pressed I called form.submit(). The key event code is really unnecessary because an enter on the text input triggers the form submit on both FF and IE. So, although on the other 2 browsers this was no problem, in WebKit this triggers 2 posts. So... just DON'T do this.

Posted by Toby about 1 year ago about chrome, crossbrowser, javascript, programming, prototype, safari and webkit (0 comments)

Play Date with jQuery

I had a new toy project and started out with my trusty sidekick: prototype.js but a bit of the way in i decide to try my hand at jQuery instead, since I've already read a lot about jQuery and really like the monad-like paradigm which allows you to write elegant "flow" code without having to worry about null values anywhere in the chain.

It was quite easy translating my existing prototype.js code to jQuery(probably just around 30 lines).
  • The end result was probably 20% more succient.
  • I love the css 3 capable selectors, it's very refreshing to be able to use attribute and partial string match selectors which normally you don't get to use for your work. 
  • I also like the way attributes are set as chained methods(again, in the monad flavor), you do something like $('#myid').attr('value') to get the value and $('#myid').attr('value', 1) to set the value to 1. This again, allows you to chain stuff together. What's the point of this? ...I guess I just like the monad thing.
  • I think the jQuery syntax for behavioral javascript is prettier than prototype.js + lowpro.js
I really have nothing bad to say about jQuery. Even the UI components seem pretty on par with prototype.js, there's jqueryui, from which I used the autocomplete plugin. It's a little bit unfortunate that I had already invested about 1800 lines of javascript code on writing javascript components based on prototype.js and scriptaculous at work, otherwise had I started over I would very probably use jQuery. I will definitely go jQuery for my other projects.

Are there anything from prototype.js that I miss? Well, yes, I miss the array extensions from prototype, which lets you use ruby/smalltalk/lisp-like internal iterator style list operations. jQuery has a $.each, but it's not quite as pretty... but it gets the job done. And I haven't looked, but I am not sure there's an equivalent to prototype's Event.KEY_RETURN, Event.KEY_BACKSPACE and such in jQuery. Also, I had gotten comfortable to the OO model from prototype, and doing without it will be different, but then again I am adaptable. Plus, there's nothing at all stopping you from using jQuery and prototype.js together.
Posted by Toby about 1 year ago about javascript, jquery, programming and prototype (0 comments)

FF3 vs FF2 setting of position and width

Wow, FF3 broke my app!

I had a line like this(sorry this code uses prototype.js, but it's not specific to it):
myDiv.setStyle({
    position: 'absolute',
    top: elmPos.top + elm.offsetHeight,
    left: elmPos.left,
    width: elm.offsetWidth - 5});


This won't work anymore because starting FF3, you can't set the attributes: top, left, width, height to numeric values anymore, they have to labeled with a unit, like so:
myDiv.setStyle({
    position: 'absolute',
    top: asPx(elmPos.top + elm.offsetHeight),
    left: asPx(elmPos.left),
    width: asPx(elm.offsetWidth - 5)});


Where asPx is:
function asPx(n){
    return n + 'px';
}

Posted by Toby about 1 year ago about crossbrowser, javascript, programming and prototype (0 comments)

Use up() instead of parentNode

With prototype.js, you should use element.up() instead of element.parentNode. This is again because of this browser difference.
Posted by Toby about 1 year ago about crossbrowser, javascript, programming and prototype (0 comments)

Prototype's Element dot extend

Element.extend is an important method is the prototype framework. It adds all the helper/mixin methods to a dom element, like this:
Element.extend(myElem);
If for some reason you have to do this manually(probably in IE), this is what you need.
Posted by Toby about 1 year ago about crossbrowser, javascript, programming and prototype (0 comments)

Constructor Chaining in Prototype

Ever wonder how to do constructor chaining in prototype.js?
Here's how:

var Person = Class.create({
  initialize: function(){
    console.log('hello world!');
  }
});
var Pirate = Class.create(Person,{
  initialize: function($super){
    console.log('before super');
    $super();
    console.log('after super');
  }
});
new Person();
new Pirate();

The $super parameter is "special", and is detected by the library. It gives you a reference to the method of the same name defined in the super class(Ruby style, basically). Notice that unlike Java, you can do stuff before super's constructor is called. For more, see here.
Posted by Toby, 宝宝妈 about 1 year ago about javascript, programming and prototype (0 comments)