Archive for August, 2007

Super Constructor Calls in JavaScript

Friday, August 17th, 2007

I have previously shown a simple system for creating “classes” in JavaScript with Java-like inheritance. One limitation of this system is that calling a superclass constructor requires you to repeat the name of the superclass at the calling site:

extcls(Point, function Rect(x, y, w, h)
{
  Point.call(this, x, y);
  this.w = w;
  this.h = h;
})

This is both ugly and unnecessarily limiting. Furthermore, there is no guarantee that the superclass constructor is actually called. In Java, the compiler automatically inserts a super() call at the beginning of a constructor if there is no explicit call to a superclass constructor. This behavior cannot be easily duplicated in JavaScript but it should at least be possible to force an explicit superclass constructor call and throw an exception if such a call does not happen.

We cannot quite use Java’s syntax, either, because firstly, the super keyword is reserved in JavaScript and secondly, we need to invoke the super call through the this object, but we can get close by calling it this.superc (with the “c” standing for “constructor”). Here’s the Rect constructor using the new syntax:

extcls(Point, function Rect(x, y, w, h)
{
  this.superc(x, y);
  this.w = w;
  this.h = h;
})

Where and how can this superc function be defined? The previous example with a base class and one subclass makes it look deceptively simple. Let’s add another class to the hierarchy:

extcls(Rect, function ColoredRect(x, y, w, h, color)
{
  this.superc(x, y, w, h);
  this.color = color;
})

When you create in instance of ColoredRect, the this.superc() call in ColoredRect has to call Rect() but the this.superc() call in Rect has to call Point(), and it’s the same this object they’re calling it on! The only way to achieve this is by reassigning superc to the correct function before each constructor is called.

Fortunately, this is possible because superc is always called from the pseudo-constructors that are passed to extcls and these pseudo-constructors are always called from real constructors which are created on the fly by extcls. We can simply assign the correct superc function in the generated constructors before invoking the pseudo-constructors. And we can make sure that superc has been called by having it set a local flag and checking that flag when the pseudo-constructor returns. Here’s the updated extcls function with the new features:

function extcls(parent, init)
{
  var cons = function cons()
  {
    var called;
    this.superc = function()
    { 
      parent.apply(this, arguments);
      called = true;
    };
    if(arguments.length == 1 && arguments[0] === cons) return;
    init.apply(this, arguments);
    if(parent && parent.__init && !called)
      throw new Error("superc() was not called in "+init.name+"()");
  };
  cons.toString = function()
    { return "[Generated constructor for class "+init.name+"]"; };
  cons.__init = init;
  if(parent)
    cons.prototype = parent.__init ?
      new parent(parent) : new parent();
  if(init.name) self[init.name] = cons;
  return cons;
}

Note that the superc() call may be omitted if no parent class has been given (in which case object is used) or if the parent class is a plain JavaScript constructor that was not defined by defcls or extcls.

Y Combinator in Java With Generics

Sunday, August 12th, 2007

After reading Y Combinator for Dysfunctional Non-Schemers I wondered how far you could go with implementing a Y Combinator in Java with generic types. And I had a strong feeling that it would be rather ugly!

I started with the call-by-value version of the Y Combinator as given by the following expression, straight from the Wikipedia page:

Z = λf. (λx. f (λy. x x y)) (λx. f (λy. x x y))

This one innocent line translates directly to the following mess in untyped Java:

static interface F { Object call(Object arg1); }
 
static F z(final F f)
{
  return (F)
  (
    new F()
    {
      public Object call(final Object x)
      {
        return f.call
        (
          new F()
          {
            public Object call(final Object y)
            {
              return ((F)((F)x).call(x)).call(y);
            }
          }
        );
      }
    }
  )
  .call
  (
    new F()
    {
      public Object call(final Object x)
      {
        return f.call
        (
          new F()
          {
            public Object call(final Object y)
            {
              return ((F)((F)x).call(x)).call(y);
            }
          }
        );
      }
    }
  );
}

It could be simplified further (it’s not necessary to create an F object at the beginning because it is called immediately) but the simplified version turned out to be even harder to annotate with generic types.

The next step was to gradually add type annotations where possible and remove the type casts. I finally arrived at this point where I could not add any more consistent annotations:

static interface F<R,P> { R call(P arg1); }
 
static <R,P> F<R,P> z(final F<F<R,P>,F<R,P>> f)
{
  return
  (
    new F<F<R,P>,F>()
    {
      public F<R,P> call(final F x)
      {
        return f.call
        (
          new F<R,P>()
          {
            public R call(final P y)
            {
              return (R) ((F) x.call(x) ) .call(y);
            }
          }
        );
      }
    }
  )
  .call
  (
    new F<F<R,P>,F<F<R,P>,F<?,?>>>()
    {
      public F<R,P> call(final F<F<R,P>,F<?,?>> x)
      {
        return f.call
        (
          new F<R,P>()
          {
            public R call(final P y)
            {
              return x.call(x).call(y);
            }
          }
        );
      }
    }
  );
}

This version still contains two casts and several type warnings due to the use of raw types. I am not sure if it would be possible to get closer to the ambiguously typed part and I didn’t want to spend any more time trying to. It was already clear that this can only serve as a proof of concept and that you would be ill advised to ever use something like this in production code.

Finally, here’s some code to show how the z function is used and that it really works:

final F<F<Integer,Integer>,F<Integer,Integer>> fac = new F<F<Integer,Integer>,F<Integer,Integer>>()
{
  public F<Integer,Integer> call(final F<Integer,Integer> rec)
  {
    return new F<Integer,Integer>()
    {
      public Integer call(final Integer i)
      {
        if(i <= 1) return 1;
        else return i * rec.call(i-1);
      }
    };
  }
};
 
System.out.println("5! = " + z(fac).call(5));

Rural Germany in the 1920s

Saturday, August 11th, 2007

A few years ago, a strip of old medium format black & white negatives came into my possession. It contains pictures taken by my grandfather in the area around his home in rural Germany in the 1920s. The exact date is unknown but one of the pictures is a self portrait, so we could at least do a rough estimate.

I was able to identify some of the locations on the pictures, so I set out out reproduce them. Matching the locations and perspectives exactly turned out to be quite difficult, and the old negatives were in a bad shape after being hidden behind a drawer in a cupboard for about 80 years, so they needed a lot of manual post-processing. I only got one picture finished and I haven’t found the time to work on the other ones in the four years since, but I’d like to take this chance to publish at least the first picture.

Here’s the original scene from the 1920s:

And this is the same place in 2003:

I’ve prepared larger versions on a separate page with a mouse-over effect that allows you to compare them easily.

Class Constructors in JavaScript

Monday, August 6th, 2007

If your previous experience with object-oriented programming has been in “classical” OOP languages like Java or C++, JavaScript’s prototype object system probably seemed strange at first. When I picked up JavaScript, it was one of the key parts for me to learn. I just wanted to see what possibilities it affords you and how a traditional class model with virtual methods, constructors, hidden state and inheritance could be mapped to JavaScript.

It turns out that a single class (if you can call it that in a classless language) is easy enough:

function Point(x, y)
{
  this.x = x;
  this.y = y;
}
 
Point.prototype.toString = function()
{
  return "(" + this.x + "," + this.y + ")";
}
 
var p = new Point(1,2);
console.log(p.toString());

Running this code gives the expected result: p = (1,2).

Now let’s write a class Rect which extends Point and adds two more fields, for the width and the height of the rectangle. The standard approach you’ll find in JavaScript tutorials is to call the Point function to create a prototype for Rect:

1
2
3
4
5
6
7
8
9
10
11
function Rect(x, y, w, h)
{
  Point.call(this, x, y);
  this.w = w;
  this.h = h;
}
 
Rect.prototype = new Point();
 
var r = new Rect(3,4,5,6);
console.log(r.toString());

Since we haven’t provided a toString method for Rect, the call to toString is delegated to Point’s original implementation, so the result is (3,4).

Line 8 highlights the problem with this strategy: You have to call the superclass constructor to create the prototype! In many cases this is not an issue. In fact, in the Rect example above, the constructor will simply assign the value undefined to the fields x and y of the Rect prototype, but if you want to be able to treat the superclass as a black box, you need a way of subclassing it without calling its constructor on a dummy prototype object.

Unfortunately, you must call the constructor to create the prototype, but you can move the initialization code to a different function instead. The actual constructor can then be created automatically by this helper function:

function extcls(parent, init)
{
  var cons = function cons()
  {
    if(arguments.length == 1 && arguments[0] === cons)
      return;
    init.apply(this, arguments);
  };
  cons.toString = function()
  {
    return "[Generated constructor for class "+init.name+"]";
  };
  cons.__init = init;
  if(parent)
    cons.prototype = parent.__init ?
      new parent(parent) : new parent();
  if(init.name) self[init.name] = cons;
  return cons;
}
 
function defcls(init)
{
  return extcls(null, init);
}

The Point and Rect classes can now be defined like this using defcls and extcls:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
defcls(function Point(x, y)
{
  this.x = x;
  this.y = y;
})
 
Point.prototype.toString = function()
{
  return "(" + this.x + "," + this.y + ")";
}
 
extcls(Point, function Rect(x, y, w, h)
{
  Point.call(this, x, y);
  this.w = w;
  this.h = h;
})

Another problem remains with this code. On line 18, the Rect constructor has to call its super constructor Point() explicitly by name, and the syntax is similar when you override a method and want to call a method of the superclass. What’s missing here is Java’s super keyword. But I’ll leave that for another post.


Close
E-mail It