Hacker News new | ask | show | jobs
by zeveb 2859 days ago
Reading https://norvig.com/python-lisp.html this morning, it appears that my conjecture is correct: Norvig uses 'object model' to mean something like 'everything is an object,' 'objects have type, variables don't' & 'introspection of objects & classes is strong.'

In that sense, Python & Lisp are similar. But I don't think that's a good use of the phrase 'object model'; I think it's more usefully applied to the model objects follow.

The really radical difference between the Lisp & Python object models is that Lisp objects don't have methods. Where in Python one adds methods to a class, in Lisp one specialises generic functions on classes — and one isn't limited to specialising on a single argument. There's no clean way in Python to implement a method that works with a Foo and a Bar: one can either implement a method on a Foo that takes an argument of any type, or a method on a Bar which takes an argument of any type (although ISTR some rumours of typed Python; dunno how that would change things, but the methods would still live inside one class or another).

In Lisp, though, generic functions are their own things: they don't live inside a class at all. One would just specialise a generic function taking two arguments such that one is a foo & one a bar.

The difference is between this:

    class Foo:
        def baz(bar):
            # bar might or might not be an instance of Bar
    
    class Bar:
        pass
or this:

    class Foo:
        pass
    
    class Bar:
        def baz(foo):
            # foo might or might not be an instance of Foo
and this:

    (defclass foo () ())
    
    (defclass bar () ())
    
    (defmethod baz ((foo foo) (bar bar))
      ;; foo is always a foo & bar is always a bar
      )
This is so unlike Python as to be unrecognisable.

There's another difference, which used to drive me crazy in Python: when I redefine a class in Python, existing instances don't get updated, so if I had a REPL with a lot of state I'd have to manually convert the old instances to new ones. But with Lisp this happens automatically, and if one needs to run extra code (say, because the old & new class differ in an important way) then there's UPDATE-INSTANCE-FOR-REDEFINED-CLASS. That, BTW, is a generic function.

That's something I really like about Lisp: like SmallTalk, it's built for programming in the large, on stable systems which have to run for a long time. 'Just reboot it' is not a very Lispy idiom.

1 comments

'object model' in Lisp has two traditional meanings. Originally data with identity is called an object. A cons cell, a vector, a string, some numbers, characters, symbols, ... all these are objects. One can reference any of them via variables, can return them from functions, give them as arguments to functions. Arguments are not copied. Function results are not copied. Etc. The JVM for example has a similar 'object model' like Lisp - thus the GLS quote: Java developers were half-way dragged to Lisp.

The second meaning is the object model in the sense of 'object oriented programming'. One of the similarities might be the use of meta-classes. Generally though CLOS isn't that near to the class-based OOP object-model of Python. CLOS uses a mixed model of classes and independent generic functions (with multiple dispatch)...