[Python-ideas] Message passing syntax for objects

Andrew Barnert abarnert at yahoo.com
Mon Mar 18 21:19:19 CET 2013

From: Mark Janssen <dreamingforward at gmail.com>

Sent: Monday, March 18, 2013 11:22 AM

>>  We need a concrete example.  Let's do `int`s.  Currently, a small 
> subset of
>>  the things we can do with ints includes multiplying, dividing, adding,
>>  subtracting, and (formatted) displaying -- how would these operations look
>>  with a message passing inteface?
> Good.  You've chosen perhaps the worst example to demonstrate the
> point, but let's see if I can turn it into an opportunity (haha).

OK, let's use your own example, which you keep reiterating:

>>> 42 >> MyCollectionType  #would add the object into your collection:  *poof*: no more random syntaxiis for putting things in collections.\

This solves the problem that list.append, set.add, etc. all look completely different. Great.

But what if I want to extend instead of appending? If you say "well, another sequence extends instead of appending", then how do I create lists with lists in them? For that matter, how do I insert at a given position, or replace a slice, or… anything besides the default? The obvious solution is that you pass some kind of wrapper message:

    Extender(lst2) >> lst1
    Inserter(3, lst2) >> lst1

But now, you're simulating separate methods by using type-switching. That's about as unpythonic as possible. And if you think about it, how can you write Inserter(3, lst2) in this everything-is-a-message syntax? It's going to get really ugly without a lot of sugar. Unless you curry the messages:

    lst2 >> 3 >> Inserter >> lst1

Here, you're not sending 3 to lst1, but to "Inserter >> lst1", a lst1-inserter object, and then you're sending lst2 to a lst1-inserter-at-position-3 object. And now you've written Reverse Haskell.

So, why doesn't Smalltalk—which, like Python, is not a type-based language—not have this problem?

I think you've fundamentally misunderstood Kay's design. Smalltalk messages have a structure: a name, and a sequence of parameters. (I'm going to use a fake Smalltalk-like syntax below, to better show off the advantages of Smalltalk and avoid getting diverted into side tracks.) For example:

    lst1 extend:lst2

    lst1 append:lst2
    lst1 insert:lst2 atPosition:3

Notice that this is almost completely isomorphic to the familiar dot syntax, just with different punctuation—space instead of dot, colon instead of comma, and the method name and parameter names intermixed. But only _almost_.

Dot syntax makes it easy to make either the parameter names or the position optional in calls, while Smalltalk-style syntax means you always need both. In other words, you can't

Second, the natural set of first-class values is different. 

In Smalltalk, "selectors" are values, while in Python, you can only accomplish the same thing through ugly string-based method lookups:

    lst1 perform:(insert:atPosition:) withArgument:lst2 and:3
    lst1.getattr('insert')(lst2, 3)

In Smalltalk, "messages" (and/or "invocations") are also values, while in Python, you have to simulate them with lambda/partial/etc.:

    message = (insert:lst2 atPosition:3)

    message = lambda lst: lst.insert(lst2, 3)

In Python, bound methods and unbound methods are values, while in Smalltalk, you have to simulate them with something like lambda (which I won't show here):

    inserter1 = lst1.insert
    inserter1(lst2, 3)
    inserter2 = list.insert
    inserter2(lst1, lst2, 3)

So, there are some minor advantages and disadvantages to each style. But ultimately, there's no real difference between them.

More information about the Python-ideas mailing list