[Python-ideas] Message passing syntax for objects

Andrew Barnert abarnert at yahoo.com
Tue Mar 19 04:12:41 CET 2013


> From: Mark Janssen <dreamingforward at gmail.com>

> Sent: Monday, March 18, 2013 6:38 PM


> On Mon, Mar 18, 2013 at 5:39 PM, Steven D'Aprano <steve at pearwood.info> 
> wrote:


>>  - we can no longer distinguish between *adding* something to an unordered
>>  collection, and *appending* to an ordered collection;
> 
> Your ClassName or __doc__ is supposed to make that clear, because your
> API doesn't.  This is the problem I'm referring to when I talk about
> "hyper-personal API's" -- you have to learn the programmer's 
> personal language.

What's hyper-personal here? Mutable sequences support effectively the same set of operations in every language. Each language may have different names for these operations, but within a language they're consistent. No matter whose Python code you're looking at, a list has the same append and extend methods—and, for that matter, so does any other class that satisfies the MutableSequence ABC, even any other type that "duck types" as a mutable sequence.

>>  - we can no longer distinguish between (for example) *appending* to the end

>>  of a list, *extending* a list with a sequence, and *inserting* somewhere
>>  inside a list.
> 
> Well, these are old data paradigm operations which will go away in my
> view.  The very thinking in terms of "lists within lists" is very
> personal and no one else will be able to use whatever you're building.

The idea of non-flat collections is certainly not "personal". Resources contain, or link to, resources, hierarchically or otherwise. Directories contain directories. Research papers reference other resource papers. Web pages link to other web pages. Documents have subdocuments. And so on. Your new paradigm has to account for that, or it's useless.

And meanwhile, the idea that "no one else will be able to use whatever you're building" if you have lists within lists is disproven millions of times per day. I just wrote and ran a script that gets a list of all movies on all channels owned by a certain YouTube user. I had absolutely no trouble using their lists within lists (actually, it's three levels deeper than that), despite the fact that I know nothing about their code, and they've never even heard of me. We just both know JSON, and that's all it takes.

>>  - we cannot even distinguish between "put this thing in your 

> collection" and
>>  "search your collection for this thing", since we're limited 
> to a single >>
>>  "send message" operator.
> 
> Ummm, perhaps you missed something in Python: "search your collection
> for this thing" is done with "in"; i.e. , "item in 
> myObject".  That
> already is TOWTDI way to do it.  Obviously, the first item is already
> handled with the messaging operator.

You've clearly missed something in Python. "item in collection" is, basically, syntactic sugar for "collection.__contains__(item)". And "collection[3]" is "collection.__getitem__(3)". And so on. It's all method calling.

More importantly, you've missed something fundamental about message passing. The whole point of the paradigm is that all operations are messages. That means you can do things like make all messages sequenced and asynchronous (as in Erlang) and get guaranteed-safe concurrency. Or make all message handling dynamic modifiable at runtime (as in Smalltalk) and have hot-swappable code. As soon as you allow end-runs around messaging to access objects directly, none of that works.

And, needless to say, this clearly requires the list type to handle multiple different kinds of methods/messages. You can dismiss the need for extend, insert, etc., but without __contains__, __getitem__, __iter__, etc., a list is completely useless—it's a write-only structure.

At this point, it's starting to feel like that NewsRadio episode where Bill interviews a "business visionary" who has something important to say about the future of computers, then admits that he's never actually used a computer, but thinks they sound neat.


>>  * Open a file with that name.

> 
> Why does everyone seem to pick the most corner-type cases?

Maybe if you gave a single good example, people wouldn't keep coming up with examples you don't like. But really, almost everyone has picked the two examples you yourself gave: appending to a list, and adding a number to a number. You've complained that those are terrible examples, and haven't given any others, so what can people do but guess what you might possibly have in mind? Meanwhile, I gave you a dozen different examples from a wide range of application areas, and you ignored them completely and went on about list appending.

> But now that you have me thinking on it, I see the file system as

> being composed of namespaces organized in a tree.  The Python
> interpreter would access them directly.

Well, because a filesystem contains links and mountpoints and other things, it isn't quite just a tree, but let's accept that.

So, I've got an object representing a directory (a subtree), say, "home", representing "/Users/abarnert". Presumably, "foo >> home" gives me the path "/Users/abarnert/foo". I can send it data to write to that file, or send data from it to read from that file. So far, so good. But how do I select a subdirectory under home? Or get a list of all files and subdirectories under home? Or move a file, or delete it, or change permissions on it, or get its size? Ultimately, there are many things i might want to do with a directory or a file, and therefore it needs multiple methods. Just like a list. Or a number. Or a document, an account, a client connection, a window, a modeled species, etc.

Being able to do multiple things is fundamental to the usefulness of objects. Something that can only do one thing isn't an object, it's a function. In fact, it's a function with a single parameter.



More information about the Python-ideas mailing list