Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Friday, May 1, 2015

Class-free object-oriented programming in Javascript

Douglas Crockford has given another talk on the future of Javascript, with particular attention to what he now considers the Right Way to do object-oriented programming, which is quite a departure from classical thought. Years ago, he stopped using new explicitly, and came up with Object.create to use instead, for more straightforward use of Javascript's prototypal inheritance design.

Now, he has also stopped using this, which means he has effectively abandoned Javascript's notion of inheritance altogether. He calls his new style "class-free object-oriented programming", the basic feature of which is that every object actually contains its own methods, rather than sharing them in a prototype or parent object. This is "inefficient" by some measure, but if you think about it, the sharing of methods is simply an optimization, and in most cases, optimizing for space in JS is not going to make a critical difference.

It happens that this was the style I adopted when I got into programming JS, because I was not trained up in classical object-oriented languages. Ironically, more recently, I did get into the typical use of new and prototypes, but I'm going to reconsider that for a while.

Crockford's basic boilerplate for a constructor is:
function constructor(spec) {
  let {member} = spec,
      {other}  = other_constructor(spec),
      method   = function () {
        // accesses member, other, method, spec
      };

  return Object.freeze({
      method,
      other,
  });
}
Which is to say that there is no built-in inheritance; objects that are composed-in are simply member sub-objects. You can, of course, make pass-through member calls.

Danny Fritz blogged about the concept of class-free OO programming, with some helpful illustrative examples, but his techniques differ somewhat from Crockford's, notably in the use of this. Predictably, I have a take that is somewhat different from each of them, but which I think marries their best features.

Crockford uses constructors for everything, which has the code smell of boilerplate in the form of the return Object.freeze portion. Fritz has constructors and extenders, with a copy-in extend function. I have always hated such extenders, and I don't see a reason to have a distinction between constructors and extenders.

Instead, I propose that the proper separation of duties is to have a universal constructor and everything else is an initializer. This gives you freedom to inherit and allows you to avoid the security hazards of this.

The universal constructor looks like this:
Function.prototype.construct = function (spec) {
    var obj = {};
    this(obj, spec);
    return Object.freeze(obj);
}     
Almost too simple to bother with, but it takes care of the boilerplate issue. Note: I formerly had defined this as Object.construct, but this definition makes every function be a potential constructor, which seemed more appropriate.

Now, for any object type (or extension type), all you have to concern yourself with is the initialization. I will illustrate using Fritz's examples of alligator, duck, and goat objects that are defined in terms of extensions Animal, Walking, Swimming, Flying. This is a straightforward port of his alligator:
function alligator (self, spec) {
    self.name = 'alligator';
    self.word = 'grrr';
    animal(self);
    walking(self);
    swimming(self);
}
All of the extensions are just initializers called on the self object (which, being passed in, avoids the security problems of this), and the alligator function is, itself, just an initializer. spec is not used in this case, but I have kept it to show how Crockford's model fits. Most objects do have inputs to their initialization. Similarly, animal et. al. would normally take a second argument.

To create an instance:
var myAlligator = alligator.construct(spec);
It should be clear from this how duck and goat would similarly be created, but let's take a look at the extensions. Again, a straightforward port of animal:
function animal(self) {
    self.name = 'name';
    self.word = 'word';
    self.talk = function () {
        console.log(self.name + ' says ' + self.word);
    }
};
It becomes clear at this point that all the things that inherit from animal have a name and a word. Initialization of those should be done with a spec, rather than having placeholder defaults and each derived object having to know about them:
function animal(self, spec) {
    self.name = spec.name;
    self.word = spec.word;
    self.talk = function () {
        console.log(self.name + ' says ' + self.word);
    }
};
Now we can rewrite alligator:
function alligator (self, spec) {
    animal(self, spec);
    walking(self);
    swimming(self);
}
alligator.construct({name: 'alligator', word: 'grrr'});
So our alligator doesn't merely contain animal, walking, and swimming objects (as would be the case in the Crockford model), but it has been initialized to have those traits directly. This requires that all the traits play nicely with each other. If that can't be guaranteed, Crockford's model offers more security, and can obviously be implemented with pass-through methods like so:
function alligator (self, spec) {
    animal(self, spec);
    var walkTrait = walking.construct();    var swimTrait = swimming.construct();    self.walk = walkTrait.walk;
    self.swim = swimTrait.swim;
}
alligator.construct({name: 'alligator', word: 'grrr'});
Note that I have initialized the alligator self as an animal, then added the other features as traits. Whether you initialize on the object itself or create sub-objects is up to you.

Monday, February 2, 2015

Exploring the smell of Javascript inheritance

In Javascript, objects inherit from other objects. By convention, the objects that are inherited from (prototypes) contain methods, while the inheriting objects contain data. This makes sense, as it is practical to share methods, but each instance must have its own data.
Given that we are interested in (only) the methods of the parent object, it strikes me as something of a code smell that inheritance is done by taking an instance of an object - including, in particular, its data members - to use as a new prototype to which we add functions. It's convenient, it's relatively low cost (what are a few unused variables, for a whole class), but you're still creating things that you will never use. For example, say we have this class:
function Button (label, position) {
  this.label = label;
  this.position = position;
}
Button.prototype = {
  // Button functions
  ...
};
You might derive a new subclass like so:
function RoundButton(size, label, position) {
  Button.call(this, label, position);
  this.size = size;
}
RoundButton.prototype = new Button();
RoundButton.prototype.newMethod = function () {
  // additional functions
  ...
};
You only create the new Button instance so you can inherit from its prototype and add methods to it. The data members don't matter at all to the prototype; you want them in the instance (hence the Button.call).
You could have the Button constructor check to see whether it receives any arguments, and if not, it doesn't create its members. That makes Button responsible for two things: constructing new buttons and constructing new prototypes for derived classes. Another approach would be to separate the prototype responsibility into another class:
function DerivedButton() {}
DerivedButton.prototype = Button.prototype;
Then RoundButton.prototype would be declared:
RoundButton.prototype = new DerivedButton();
Interestingly, because DerivedButton and Button share a prototype, deriving RoundButton from DerivedButton will make RoundButton instanceof Button yield true.
It looks like Object.create was set up to have prototypes inherit through prototypes and not through object instances (as well as to facilitate more traditional object-oriented features).

Thursday, August 5, 2010

A little JavaScript™ Invention

One deficiency in JavaScript™ is that it has no sleep command. Instead, it has a setTimeout function, which works differently: you tell it what you want to run, and how long you want it to be before it starts, and that acts like a little time bomb in the background while your program continues on. It doesn't pause. So if you want it to actually pause, you need to pass the entire rest of your program in.

That sounds crazy, and it kind of is. But JavaScript™ (I'm writing it that way because it really is a trademarked name) is for web apps, where you don't really run a whole program. What you're usually writing is callbacks for widgets. It's a callback-oriented language.

So today, I had the need to put a pause in a series of requests I was making, so that they wouldn't all happen at once. How to do that as I'm looping through the array? Tail-recursion, of course— that's how you loop in a functional language. I came up with a function that works like the forEach method, only it has a specified pause before invoking the callback:

          // Like forEach, but with a delay
function delayForEach (queue, callback, delay) {
var qIdx = 0;
// recursive block
(function () {
if (qIdx < queue.length) {
callback(queue[qIdx], qIdx);
++qIdx;
setTimeout(arguments.callee, delay);
}
})();
}

It's just a little thing, but I thought it was nicely elegant. It should be noted that this call will all run "in the background": if you call delayForEach on some array, your program will continue on, and the looping will be done as if it were running independently. Still, could be useful for somebody.

Upon reflecting a bit, it seems to me that it might be more appealing to use setInterval instead.

         function delayForEach (queue, callback, delay) {
var qIdx = 0,
interval = setInterval(function () {
if (qIdx < queue.length) {
callback(queue[qIdx], qIdx);
++qIdx;
}
else {
clearInterval(interval);
}
})();
}

Wednesday, August 4, 2010

Deriving the Y Combinator

The Y-Combinator Derived

The Y-Combinator was something that came up in my Programming Languages class at Rice. It was bizarre and inscrutable to me, and I never really acquired a deep understanding of it. Frankly, it doesn't have a lot of practical application, but it is interesting. And Douglas Crockford said something like, "If you understand this, you can call yourself a computer scientist." Well, I certainly want to be able to do that. And maybe this post will create a few more computer scientists. I hope so.

First, I want to note that I depended heavily on this page for my derivation steps. I changed them as I saw fit, but it was nice to have them to refer to when I screwed up.

My intent is to derive the Y-Combinator in a way that makes it obvious what's going on. This subject has been done quite a few times (and in quite a few languages), but they always use meaningless function and variable names, and I find that makes it hard to follow. So I'm taking my stab at it. I've been writing in JavaScript lately, so that's what I'm using here.

The first step on that road is to understand what we're deriving. The Y-Combinator is a function that provides "anonymous recursion". That is, if your language doesn't provide a way for a function to call itself while it is being defined, the Y-Combinator can give you that.

Specifically, let's say you have a function that you can tell how to call itself, and then it can be recursive:

function factorial (myself, n) {
return n <= 2 ? n : n * myself(myself, n - 1);
}

What you want, though, is a function that doesn't have to tell itself how to call itself every time.

// This doesn't work. We need "myself" to be defined somehow
function factorial_wish (n) {
return n <= 2 ? n : n * myself(n - 1);
};

The first step is to "curry" myself out of the original function:

function curried_function (curried_self) {
return function factorial (n) {
return n <= 2 ? n : n * curried_self(curried_self)(n - 1);
}
}

With this, curried_function(curried_function) returns the factorial function you want, which you can then call with a single argument, and it will work:

var working_factorial = curried_function(curried_function);
working_factorial(5) // returns 120

But what we really want is for the factorial function to reference itself, and not the curried outer function, so that it would be written more like factorial_wish above.

We do that by wrapping a function around it that will define myself for it, and will take care of calling curried_self with itself.

function curried_v2 (curried_self) {
return function factorial (userArgument) {
var inner = function(myself) {
return function(n) {
return n <= 2 ? n : n * myself(n - 1);;
};
};
var myfact = inner(curried_self(curried_self));
return myfact(userArgument);
};
};

Now the innermost function is in the form we want; the function that wraps it, inner, defines its myself for us. The function that wraps that is our new factorial function, which will be what we pass an argument to, and which takes care of the curried mess.

The use of the variables is not strictly necessary here, but it helps make clear what's going on. In programming, it is often a bad practice to combine multiple operations into one monolithic, incomprehensible statement. But in math, it is called "reducing", and it's good. And the Y-Combinator comes from math called Lambda Calculus. We're just trying to understand it in terms of programming.

The calling of this hasn't improved. You still have to call it with itself to get your factorial function out:

var working_factorial = curried_v2(curried_v2);
working_factorial(5)

What has improved is that the inner function is independent of the stuff it's wrapped in, so it can be pulled out, and you'll note that it looks exactly like the factorial_wish function from earlier, wrapped in a function that takes a myself. So what remains is (almost) the goop we're looking for.

var inner = function(myself) {
return function(n) {
return n <= 2 ? n : n * myself(n - 1);
};
};

function curried_v2a (curried_self) {
return function factorial (userArgument) {
// inner was here, and is still needed
var myfact = inner(curried_self(curried_self));
return myfact(userArgument);
};
};

So the next thing to do is to pass inner to our function, so it's not hard-wired to look at some global(ish) variable. We'll do this by (of course!) wrapping it in yet another function layer, where we can do the double call, as well:

function basically_Y (inner) {
function curried_v2a (curried_self) {
return function (userArgument) { // not necessarily factorial, any more
var myfact = inner(curried_self(curried_self));
return myfact(userArgument);
};
};
return curried_v2a(curried_v2a);
}

To use this, we pass in the inner function we previously extracted (or any function that is built like it), and we will get back a well-behaved recursive function that knows how to call itself.

var myfact = basically_Y(inner); // using the inner defined earlier
myfact(5)

All that's really left is generalizing it to handle more than one userArgument.

function Y (inner) {
function curried_v2a (curried_self) {
return function (/* any number of user arguments */) {
// .apply(null, arguments) is how you pass along all arguments
return inner(curried_self(curried_self)).apply(null, arguments);
};
};
return curried_v2a(curried_v2a);
}

I went ahead and substituted in for myfact, since it's not all that complex, (not to mention that this is no longer just about factorials) but I have retained the variable that is curried_v2a.

To get to the no-variables form, we do a little re-writing: Instead of defining curried_v2a, we create a function that takes it as a parameter, and then pass its definition to that function. The function does the calling-it-on-itself part, and we're done!

function Y (inner) {
return function(curried_v2a) {
return curried_v2a(curried_v2a);
}(function(curried_self) {
return function() {
return inner(curried_self(curried_self)).apply(null, arguments);
};
});
}

It's still incomprehensible, but if you've been through the derivation, the parameter names might jog your memory about what's what.

Friday, July 2, 2010

Javascript and Dojo

Since I don't have any theater projects coming up, I figured I might as well fill in the space with what I'm doing at work. My latest gig is working with Javascript and (in particular) the Dojo toolkit to develop some web apps.

In the process of coming up to speed on Javascript and Dojo (neither of which I have used a great deal), I'm hitting Google a lot to learn how the various things work. There is, of course, some level of documentation on everything at the Dojo site, but in some cases it's incomplete, and I have to look elsewhere for someone to explain it better. So in the hopes that maybe someone else will be doing the same sort of thing someday, I'm offering this post to explain how dojo.deferreds work.
Update: Naturally, an updated version of Dojo has made this whole discussion nearly obsolete. The new features in the deferred are more intuitive.

What is a dojo.deferred?

In short, a dojo.deferred is an alternative to threads, a way of having relatively independent parts of your program running at that same time. As the documentation page says, "threads are hard."

Think of it as a chain of functions, which you build up one link at a time. You schedule them in the deferred, and kick it off, and it will work its way through them while the rest of your program continues to run uninterrupted (particularly useful if it's a time-consuming operating like waiting for a response from some remote server). If it reaches the end of its chain, it will sit and wait until you put another link on it.

Each link in the chain is a pair of functions. Which of them is called depends on what the previous link returned: if it returned an error, the errback function of will be called; if it returned a normal value, the callback function will be called. So it is critical that each function return something.

Building the chain

There are four possible functions you can call to add a link to the chain: addCallback, addErrback, addBoth, and addCallbacks, and which you call depends on whether you want to specify just a callback, just an errback, the same function to be run in either case, or separate functions for each. In general, the first link in the chain can be just a callback, because there's no danger of an error preceding it. But subsequent links should include both; if a piece unexepectedly ends in error and you have no errback to handle it, the whole deferred silently grinds to a halt.

Kicking it off

It might not be obvious that you have to actually start the chain processing. It doesn't start chugging immediately, you have to "prime the pump" with something for it to consider as the return value of the previous link. You do this by calling its callback() method, which you pass whatever value you want sent to your first callback.

Example time

I find that most examples are too detailed, so I'm going to keep this one more abstract, so that you see what the deferred is all about and don't get lost in the weeds.


//Let's say we have some functions we're going to chain up
/*
* The deferred is going to call each with the
* result returned by the previous one
*/

function thing_one(i) {
return 'Done with 1';
}
function thing_two(result) {
return 'Done with 2';
}
function thing_three(result) {
return 'Done with 3';
}

/* And here's a generic error function to
* use for every step
*/
function myErrback(e) {
alert("Some step of the deferred returned an error!");
}

// Create the deferred
my d = new dojo.Deferred();
// Chain up the steps
// No chance of failure, so no errback on the first
d.addCallback(thing_one);
d.addCallbacks(thing_two, myErrback);
d.addCallbacks(thing_three, myErrback);
// Kick it off by passing 'Go!' to thing_one
d.callback('Go!');

Note that even after you kick it off, you can add more function pairs to the chain, and they will be processed in the order received. I hope this helps somebody understand this nifty tool.