KludgeCode

is Ben Rudgers

From OOP to Lisp: Part A

In a OOP-langp tutorial – I am using psuedo-C# – we might be given an example to set up a banking account for an account object with the following code:

   Account myAccount = new Account(100);

If we  needed fifty bucks we would expect to use something like:

   myAccount.withdraw(50); 

and if we attempted to get a grand, we would expect an error message to be generated from the call:

   myAccount.withdraw(1000);

Likewise

    myAccount.deposit(1000); 

after the first withdrawal would be expected to tell us that we were thousandaires with $1050 in myAccount.

All this is pretty much standard fair, but what does it look like in a Lisp [scheme] without using objects? Well it starts off pretty similar:

   (define myAccount (make-account 100))

And if we can get past some minor points of syntax, withdrawing fifty bucks and depositing 1000 look pretty close:

   (myAccount 'withdraw 50)
   (myAccount 'deposit 1000)

And this is surprising, at least to me, because I always imagined that OOP relied on voodoo and mojo until I came across this example in Structure and Interpretation of Computer Programs which instead of being built on top of an object oriented language, is just made up of normal Scheme like this:


(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)

Where is the paradigm? The whole thing is built out of air and define from normal Scheme in fifteen lines of proper formatting. The equivalent as a class definition in C# is twenty three line – seven of which carry only a brace so it is of equivalent length:


class Account
{
    private decimal balance;
    public Account(decimal amount)
    {
        this.balance = amount;
    }
    public decimal withdraw (decimal amount)
    {
        if (balance >= amount)
        {
            balance -= amount;
            return balance;
        }
        Console.WriteLine("Witdrawal attempt failed.");
        return balance;
    }
    public decimal deposit (decimal amount)
    {
        balance += amount;
        return balance;
    }
}

I should have seen this coming when Ableson and Sussman first mentioned constructors and selectors – I just hadn’t bought into the whole conjuring and magic idiom yet. But this morning I reread

(myAccount 'withdraw 50)

and realized that but for two extra spaces characters and swapping the period for a quote,* it’s an anagram of:

myAccount.withdraw(50);

.
I'm thinking two extra spaces is a small price to pay for not having to swap paradigms. Now all I need to do is get the image of a naked wizard behind the curtain out of my head.

[Edit] After previewing this post, what is strange is how much more compact the Lisp constructor looks to me compared to the C# version. It just looks dense, like a book. Maybe that's why only certain people are attracted to it?

*And a semicolon! How could I forget the semicolon?