Saturday, January 22, 2011

Reason #23 you should read Abelson & Sussman

I'd forgotten just how great The Structure and Interpretation of Computer Programs is. I'm working my way through my ancient copy of the first edition. As their example of object-oriented programming in Lisp, you might expect that they would use CLOS, or maybe Symbolics Common Lisp with its nifty mixins*. No, they go for the throat:

(define (make-account balance)
  (define (withdraw amount)
     (if (>= balance amount)
         (sequence (set! balance (- balance amount))
                   balance)
          "Insufficient Funds"))
  (define (deposit amount)
     (set! balance (+ balance amount))
     balance)
  (define (dispatch msg)
     (cond ((eq? msg 'withdraw) withdraw)
           ((eq? msg 'deposit) deposit)
           (else (error "Unknown request"
                        msg))))
  dispatch)


==> (define acc (make-account 100))

==> ((acc 'withdraw) 50)
50

==> ((acc 'withdraw) 60)
Insufficient Funds


The beauty of this example is that it is the object-oriented programming model distilled right down to its essence.  It is succint and to the point.  No need to explain about how the compiler is providing syntactic sugar, it's just straight to the bare metal: an object is a collection of functions and data tied together -- a collection of related closures, really. 

Additionally, their discussion of the OO paradigm doesn't start with talk of "objects" and "messages", it starts with a well-grounded discussion of the programming model and its implications for the structure of your code.  I like that, because that's what Object-oreinted programming is.  All that business about objects, messages, and domain models -- that's how we choose to explain object-oriented programming.   

There's other great stuff in the book, of course.  This is just the bit that I'm loving right now. 

For the Lisp-challenged, here's how the code worksmake-account is a function that returns an anonymous function, let's call it mike.  In the code above, mike is given a name by being bound to acc.  The purpose of  mike is to dispatch calls to withdraw or deposit.  When you call mike, you will pass in either 'withdraw or 'deposit.  Based on which of those you pass in, mike will then return one of the mike-local functions  withdraw or deposit.  This returned function takes a number and returns a number, as shown in the last couple of interpreter commands above.  

Coming soon:  a couple of more blogs posts inspired by SICP.  So why aren't you getting inspired?  Read it already. 


*Well, other that they are using Scheme.   

14 comments:

  1. I am know very little about programming except the basic. However, I am to understand Lisp more than I can any other programming language. Makes me want to buy a hard copy of the book. Thanks.

    ReplyDelete
  2. The book is very good, and well worth the effort. It assumes very little knowledge on the part of the reader, and it sounds like it would be a good match for you.

    ReplyDelete
  3. This comment has been removed by the author.

    ReplyDelete
  4. Can you give this post (and subsequent posts) a label such as "sicp"? That makes it easier to link to and follow the complete series. Thanks!

    ReplyDelete
  5. Axel -- great suggestion, done.

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete
  7. I like that, because that's what Object-oreinted
    programming is. All that business about objects,
    messages, and domain models -- that's how we choose to
    explain object-oriented programming.


    Nooooo! That's backwards. Object Oriented Programming is not about objects but about messages. It is structuring programs as a set of objects passing passing messages to each other - if you take Alan Kay's word for it.

    What is shown here is one way you implement an object model in the most essential sense - a message dispatch mechanism and encapsulated state using a closure.

    ReplyDelete
  8. Duke,

    I'm not sure how your statement relates to my claim; I think we've both been less than totally clear. My claim is not related to this particular implementation; my claim is that Object Oriented Programming is an organizing principle for software whereby collections of related closures are the fundamental items being manipulated and that all state information is encapsulated in such items, hiding the state information from other such items. Whether we call these collections "objects" or whether we call them "structs" or "bumblebees" is totally irrelevant. IMO, calling them objects tends to confuse beginners and lead to poor designs; people somewhat naturally see a heirarchy of real-world "objects" and think that their software "objects" should follow it. See this paper by Robert Martin.

    ReplyDelete
  9. my claim is that Object Oriented Programming is an organizing principle for software whereby collections of related closures are the fundamental items being manipulated

    This is true, but not the essence of OOP. Interestingly, Alan Kay said that the biggest mistake he made when he invented Object Oriented Programming was using the word "object". His intent was to focus on the messaging, but everyone started focusing on the objects.

    Yes, the objects are being manipulated, but the "how" is more important than the "what". That is, the important thing is not that objects are being manipulated, but that messages are being sent to trigger the manipulation. Check out Alan Kay's explanation.

    Incidentally, it was that very paper you link (which is a chapter in Bob Martin's book Agile Principle, Patterns and Practices), which brought me to this viewpoint.

    I think there is a very subtle difference in what we're saying, and maybe I'm not doing a good job making that difference clear. Also, it may be a difference without distinction :-)

    ReplyDelete
  10. PS - by Alan Kay's definition, Erlang - with it's Actor model - is probably one of the most pure Object Oriented Programming languages, regardless of what Joe says ;-)

    ReplyDelete
  11. I definitely *think* there's a difference...but I'm not sure. For me, the essence of the model is the underlying structure not the words we use to describe it. When you say "his intent was to focus on the messaging," I'm not really sure how to interpret that in terms of the underlying structure (and to be honest, the linked article doesn't help a great deal...I'm sure that when he says "get rid of data", he means something specific, but I have no idea what it is).

    Anyway, when I read the paragraph below, I think it's all about the "how we explain this thing to ourselves" rather than the "what it is." Now of course that's a very modern-day take on the quote, and it's very possible that Kay was just trying to communicate that the underlying structure was very different from what else was standard at the time.


    - I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages (so messaging came at the very beginning -- it took a while to see how to do messaging in a programming language efficiently enough to be useful).

    ReplyDelete
  12. For me, the essence of the model is the underlying structure

    Maybe it might help if you expand on this. Let's consider Uncle Bob's article, since we're both familiar with it.

    The first part of the chapter goes over a "naive" object model, and explains why it is suboptimal. I think the key mistake he highlights is that we look at the problem as a collection of objects rather than as communicating entities. By focusing on the structure rather than the communication, we end up with a bunch of objects that don't do much except wrap over the hypothetical API.

    The second part of the chapter focuses on deriving the object model from the communication patterns - a ContainmentVessel sending a "start" message to a HotWaterSource, the UserInterface sending an "isReady" to the ContainmentVessel and HotWaterSource.

    So the question is, what is driving the direction of abstraction and the shape of the model? We agree that using objects to model physical reality is a bad idea. But do we come up with objects and *then* figure out how they will communicate, or do we derive the communication pattern and *then* derive the objects that will facilitate it? Maybe it's a bit of both?

    It seems more than "how we explain this thing to ourselves" - there is an essence here that shapes our "worldview" and how we drive the modelling process. It's the difference between Reductionism vs Holism, I think.

    I may be splitting hairs though ;-)

    ReplyDelete
  13. I think I see the difference in our approaches. I'm more concerned with 'what is an Object-Oriented Program' (ie, the structure of the program itself) and you seem to be focusing on 'Object-Oriented ProgrammING' -- ie, how we get there.

    ReplyDelete