Warning: This article is intended for JavaScript programmers. Parens are coming but only briefly and you can handle it and it will be good for you.

In Structure and Interpretation of Programming Languages Second Edition (SICP) on page 182, the authors introduce the idea of message passing with the following example in Scheme of a complex number constructor function.

(define (make-from-real-imag x y) (define (dispatch op) (cond ((eq? op 'real-part) x) ((eq? op 'imag-part) y) ((eq? op 'magnitude) (sqrt (+ (square x) (square y)))) ((eq? op 'angle) (atan y x)) (else (error "Uknown op -- MAKE-FROM-REAL-IMAG" op)))) dispatch)

The important part to note here is that the value returned by the make-from-real-imag constructor function is actually a dispatch procedure that you can call with a message argument. You can send messages to get the real part or magnitude of the complex number.

(define c (make-from-real-imag 3 4)) (c 'real-part) ; 3 (c 'imag-part) ; 4 (c 'magnitude) ; 5 (c 'angle) ; 0.927295218001612 (c 'asdf) ; ERROR: Uknown op -- MAKE-FROM-REAL-IMAG: asdf

Let’s see what the above code looks like in JavaScript, our lingua franca.

function makeFromRealImag(x, y) { function dispatch(op) { switch (op) { case 'realPart': return x; case 'imagPart': return y; case 'magnitude': return Math.sqrt(x*x + y*y); case 'angle': return Math.atan2(y, x); default: throw 'Unknown op -- makeFromRealImag: ' + op; } } return dispatch; } var c = makeFromRealImag(3, 4); c('realPart'); // 3 c('imagPart'); // 4 c('magnitude'); // 5 c('angle'); // 0.9272952180016122 c('asdf'); // "Unknown op -- makeFromRealImag: asdf"

Now this probably doesn’t look like any object-oriented JavaScript you’ve seen before but it illustrates an important point. In JavaScript, we can represent the idea of an object as a function of its messages. The constructor function returns a dispatch function that you wrote that can dispatch any message any way that you want it to. This immediately gives you Spidermonkey’s __nosuchmethod__ , Smalltalk’s doesNotUnderstand , and Ruby’s method_missing . Powerful stuff but unfortunately the JavaScript code above runs very slowly. We can move towards a faster and more familiar JavaScript style.

SICP page 223, introduces the idea of mutable objects but the most interesting point is the variation on the dispatch procedure.

(define (make-account balance) (define (withdraw amount) (if (>= balance amount) (begin (set! balance (- balance amount)) balance) "Insufficient funds")) (define (deposit amount) (set! balance (+ balance amount)) balance) (define (dispatch m) (cond ((eq? m 'withdraw) withdraw) ((eq? m 'deposit) deposit) (else (error "Unknown request -- MAKE-ACCOUNT" m)))) dispatch) (define account (make-account 10)) ((account 'deposit) 5) ; 15 ((account 'withdraw) 3) ; 12

Converting this to JavaScript we have the following.

function makeAccount(balance) { function withdraw(amount) { if (balance >= amount) { balance = balance - amount; return balance; } return "Insufficient funds"; } function deposit(amount) { balance = balance + amount; return balance; } function dispatch(m) { switch (m) { case 'withdraw': return withdraw; case 'deposit': return deposit; default: throw "Unknown request -- makeAccount: " + m; } } return dispatch; } var account = makeAccount(10); account('deposit')(5); // 15 account('withdraw')(3); // 12

The way the dispatch function works for accounts is quite different than in the complex numbers case. In the case of complex numbers, when a message was sent to the dispatch function, it executed the associated operation (i.e. the method) immediately. In contrast, the account dispatch function returns the method associated with the message and that method can then be called.

This is very similar to how JavaScript’s reciever.message(arg) syntax works and we can move to a more familiar object-oriented JavaScript style.

function makeAccount(balance) { function withdraw(amount) { if (balance >= amount) { balance = balance - amount; return balance; } return "Insufficient funds"; } function deposit(amount) { balance = balance + amount; return balance; } return { withdraw: withdraw, deposit: deposit }; } var account = makeAccount(10); account.deposit(5); // 15 account.withdraw(3); // 12

In this last version, we’ve stopped writing our own dispatch logic and use JavaScript’s built-in property lookup. This increases speed significantly. We’ve lost the ability to do the __noSuchMethod__ type of dispatching when using standard ECMAScript but that doesn’t seem to be commonly useful anyway.

For the well-read JavaScript programmers out there, you may recognize this last version as durable objects from Douglas Crockford’s book JavaScript: The Good Parts.

I find it interesting that the word “inheritance” does not appear in SICP’s index even though the book goes on to implement complex programs like language interpreters and compilers in a message passing style. That shows this simple style of object-oriented programming can take you far.

The moral of the story is that old books are worth reading and can change the way you program today. You can even read SICP for free.