This

JavaScript functions always get a reference to an object called this. If you just invoke a function f(), then this is bound to the global scope object in older browsers and to undefined in newer ones.

Method invocation is a special form in JavaScript: if you invoke a property of an object o.f(), then this is bound to the object o. If you don’t want this bound to o, then you have to break up that special form. You can either assign the function to a variable and invoke that:

var g = o.f;
g();

or you can make a reference to o be the result of a subexpression and then invoke the f property on that:

(1,o).f()

In the example of the person interface, the print function took a name and an age as explicit parameters. The OOP way of doing it, of course, would be to use this.name and this.age:

var person = makeInterface({
  name: str,
  age: nat32
});

var print = function () {
  person(this);
  return str(this.name) + ' is ' + 
      nat32(this.age) + ' year' +
      ((this.age === 1) ? '' : 's') + 
      ' old.';
};

var joe = person({
  name: 'Joe Brown',
  age: 35,
  print: print
});

joe.print();

This is a lot better, but we’d still like to be able to use hom to express typing decisions. Instead of trying to shoehorn this into hom, we can write a function for labeling functions that should be called as methods on an object satisfying the interface.

// Captures the hom contract instance
var method = function (homDecl) {
  // Returns a higher-order contract that
  // gets applied when the interface contract
  // is applied to the object
  return function (f) {
    // Binds to the interface contract
    var intr = this;
    var g = homDecl(f);
    // Returns a function that behaves like f
    return function (varArgs) {
      return g.apply(intr(this),
        toArray(arguments));
    };
  };
};

var person = makeInterface({
  print: method(hom([], str)),
  name: str,
  age: nat32
});

var joe = person({
  name: 'Joe Brown',
  age: 35,
  print: function () {
    return name + ' is ' +
        this.age + ' year' +
        ((this.age === 1) ? '' : 's') +
        ' old';
  }
});
Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: