Pascal and his Camels

Camel Case is where instead of spaces you capitalise the first letter of each word:

thisIsInCamelCase

Pascal Case has the additional restriction that the first letter is capital:

ThisIsInPascalCase

It’s important to use one of these in programming because variable names and function names can’t have spaces in them.  By convention, JavaScript uses Camel Case for almost everything.  Variable names and function names should always start with a lower case letter, unless the function is a constructor.  If you don’t stick to this pattern it will be something you come to regret as these conventions make it much easier for someone else to understand how your code was meant to work (or for you to understand it in a few years time).

Constructors

So, I mentioned constructors didn’t need to start with a lower case letter.  In fact they must start with a capital letter (if you don’t want to confuse a lot of people).  The question is, what is a constructor?

My post on functional JavaScript showed a method called cons which was short for constructor since that method constructs a stream.  It’s not really how you should write a constructor though.  Today we’ll look at writing a better one.

function Stream(head, tail) {
/// <summary>A constructor for a stream</summary>
/// <param name="head" type="object">The head of the stream</param>
/// <param name="tail" type="function">The function to get the tail of the stream</param>
/// <returns type="Stream" />
this.head = head;
this.tail = tail;
}

OK, lots has changed here since last time, but we’re still essentially doing the same thing.  We’ve said this is a constructor already so we denote that by giving it a capital as the first letter of its name.  That means we can name the function after what it constructs (a Stream).

Inside we use 4 special comments which are in the vsdoc format.  These don’t actually do anything but they do allow devlopment tools to give you help when you’re using this function at a later date.

We then have something that’s entirely new.  The “this” keyword.  If you were to call this function in the normal way, it would fail completely.  For this function to work you need to give it something for this, which is then automatically returned at the end.  To do that, you simply use the new keyword before calling it.

function makeInts(n){
 return new Stream (n, function(){return makeInts(n+1);});
}

The new keyword calls the function as a constructor and gives it a value for this. Initially this is just a blank object, and then the constructor can add to it.  Initially this may seem a little pointless, but it makes a lot more sense once you start using prototypes etc.

The Prototype

When we construct an object in this way, it has a prototype.  The prototype can have functions and properties in exactly the same way as the object can have functions and properties.  When you ask for a property or function of the object, it will see if it exists on the object, and return that if it does, but if it doesn’t it will check the prototype and use that.  What this means, is that we can extend our Stream object like this.

function Stream(head, tail) {
/// <summary>A constructor for a stream</summary>
/// <param name="head" type="object">The head of the stream</param>
/// <param name="tail" type="function">The function to get the tail of the stream</param>
/// <returns type="Stream" />
this.head = head;
this.tail = tail;
}</pre>
Stream.prototype.map = function (fn) {
 /// <summary>Maps the stream onto a new stream using the function</summary>
 /// <param name="fn" type="function">The function to use for the mapping.</param>
 /// <returns type="Stream" />
 var source = this;
 return new Stream(fn(source.head), function (){ return source.tail().map(fn); });
}
Stream.prototype.filter = function (fn) {
 /// <summary>Filters the elements in the stream to include only those elements for which the function returns true</summary>
 /// <param name="fn" type="function">A function that returns a boolean for each element in the stream.</param>
 /// <returns type="Stream" />
 var source = this;
 while (fn(source.head) === false) {
 source = source.tail();
 }
 return new Stream(source.head, function (){ return source.tail().filter(fn); });
}

That gives us our map function (almost identical to our old map function) and a filter function,  I’ll leave it up to you to work out what that does.  The neat thing is that these functions belong to all streams as long as we use the Stream constructor.  That means we could do something like the following.

var evenSquares = makeInts(1)
.map(function (n){ return n * n; })
.filter(function (n){ return (n % 2 == 0); });

We can chain the calls in this way because map and filter both return Streams themselves.

Prototype Chaining

What you might be thinking now is that makeInts is really a constructor for another type of object.  Lets call this new type of object an IntStream.  Now, the problem is that IntStream is not really a completely new type of object, it’s a special type of Stream.  That means we still want it to benefit from our map and filter functions.  In most strongly typed languages, this is where you use inheritance, and indeed you can implement inheritance in JavaScript.  The prototype library is worth a look if you want a more traditional system of inheritance and I intend to review its use in a later post.

JavaScript supports an alternative method of dealing with this situation called Prototype Chaining.  The point is that our prototype for the Stream is just an object.  We’ve then added map and filter functions to the prototype, but we could replace the prototype with any object, including a Stream.  I’m going to start by showing you something which seems very simple and will work great in this situation, but is a bad idea because it won’t generalise to anything more complex.

function IntStream(start) {
 this.head = start;
 this.tail = function (){ return new IntStream(start + 1); };
}
IntStream.prototype = new Stream();
IntStream.prototype.square = function () {
 return this.map(function (n){ return n * n; });
}

So what we’ve done seems great at first glance.  We start by making this a constructor by giving it a capital I.  We assign our values for head and tail.  We tell it to use an instance of Stream as its prototype and we then define a new function, square which gives the square numbers.

Why this is good:

  • You can clearly see what’s going on, the values are assigned in a standard sensible way and we can see where the prototype comes from
  • Creating a stream with empty arguments works because the Stream constructor doesn’t throw any errors if the arguments are undefined

Why this is bad:

  • It relies on us knowing the exact implementation of Stream to assign head and tail correctly
  • If Stream had a more complex constructor we would have a lot of repetition in our code
  • Constructing Stream with no arguments only works because we were lucky.

So, how do we fix this? firstly we need to change the constructor of Stream so that it handles not receiving any arguments much more efficiently:

function Stream(head, tail) {
/// <summary>A constructor for a stream</summary>
 /// <param name="head" type="object">The head of the stream</param>
 /// <param name="tail" type="function">The function to get the tail of the stream</param>
 /// <returns type="Stream" />
 if (arguments.length === 0) {
 return;
 }
 this.head = head;
 this.tail = tail;
}

That way we can be sure that the following line won’t cause any problems:

IntStream.prototype = new Stream();

Then we modify our IntStream constructor so it doesn’t rely on knowledge of how Stream works.

function IntStream(start) {
Stream.call(this, start, function (){ return new IntStream(start + 1); });
}

OK, if that seemed crazy, don’t panic.  functions in JavaScript are just a special type of object.  In fact they have a constructor called Function and a prototype Function.prototype.  This prototype has a number of methods, two of the most useful being call and apply.  Both of them allow you to choose what this will mean inside the function, and also to pass some arguments.  You use call when you know how many arguments you are giving the function and apply when you just have an array of arguments.

We use call here to give it the same value of this that we already have, and to give it appropriate values of head and tail.  It then sets this.head and this.tail for us as it should.  As an example of how this could have gone wrong, consider the following modified definition for Stream.

function Stream(head, tail) {
/// <summary>A constructor for a stream</summary>
 /// <param name="head" type="object">The head of the stream</param>
 /// <param name="tail" type="function">The function to get the tail of the stream</param>
 /// <returns type="Stream" />
 if (arguments.length === 0) {
 return;
 }
 var self = this;
 this.index = 0;
 this.head = head;
 this.tail = function () {
 var t = tail();
 t.index = self.index + 1;
 return t;
 };
}

This keeps track of the index of the current element for us.  With our new definition for IntStream this works just fine, but with our old definition it wouldn’t have worked at all well.  Instead the index would always have been 0 (unless you first pass it through map or filter which fix the problem).  Doing it correctly may add a little more code, but it makes for a much more maintainable system, especially when dealing with something more complex than streams.  I’d suggest at this point you try and get your head around why map and filter still work and keep track of the index properly, at first glance I had thought filter would need updating to do this properly, but it doesn’t.

As a side note, I wouldn’t actually recommend creating IntStream as a constructor, it’s easier and simpler to just have makeInts in this example, but I wanted to have a good example of how you would go about dealing with something a little bit more complex.

Advertisements