[Python-ideas] Message passing syntax for objects

86 views
Skip to first unread message

Mark Janssen

unread,
Mar 17, 2013, 11:53:17 PM3/17/13
to Python List, Python-Ideas
Hello,

I just posted an answers on quora.com about OOP (http://qr.ae/TM1Vb)
and wanted to engage the python community on the subject.

Alan Kay's idea of message-passing in Smalltalk are interesting, and
like the questioner says, never took off. My answer was that Alan
Kay's abstraction of "Everything is an object" fails because you can't
have message-passing, an I/O task, working in the same space as your
objects -- they are two very different functionalities and they have
to be preserved **for the programmer**.

This functional separation made me think that Python could benefit
from a syntactical, language-given separation between Classes and the
messages between them, to encourage loosely-coupled, modular OOP.
Something that OOP has always promised but never delivered.

I think we should co-opt C++'s poorly used >> and << I/O operators
(for files) and re-purpose them for objects/classes. One could then
have within interpreter space, the ability to pass in a message to an
object.

>>> 42 >> MyObject #sends 42 as a message into MyObject

The Object definition would then have special methods __in__ to
receive data and a special way of outputing data that can be caught
__str__(?).

I'm hoping the community can comment on the matter....

Thanks,

Mark
Tacoma, Washington
_______________________________________________
Python-ideas mailing list
Python...@python.org
http://mail.python.org/mailman/listinfo/python-ideas

Ian Cordasco

unread,
Mar 18, 2013, 12:00:46 AM3/18/13
to Mark Janssen, Python-Ideas
What then happens to the binary shift operators: >> and <<? Those are
defined by __rshift__ and __lshift__ (respectively) on an object
already (help(int)). You could co-opt those operators with those
methods on your object but that would probably confuse plenty of
people. It's an interesting idea otherwise.

Mark Janssen

unread,
Mar 18, 2013, 12:07:56 AM3/18/13
to Ian Cordasco, Python-Ideas
>> I think we should co-opt C++'s poorly used >> and << I/O operators
>> (for files) and re-purpose them for objects/classes. One could then
>> have within interpreter space, the ability to pass in a message to an
>> object.
>>
>>>>> 42 >> MyObject #sends 42 as a message into MyObject
>>
> What then happens to the binary shift operators: >> and <<? Those are
> defined by __rshift__ and __lshift__ (respectively) on an object
> already (help(int)). You could co-opt those operators with those
> methods on your object but that would probably confuse plenty of
> people.

Ah right. But then, the shift operators pale in comparison to a
uniform way of passing messages between objects.

By building it into the language, it would *enforce* a modular object
style, rather than the current, very specialized and very programmer
specific way there is now. In fact, most people never really think in
that paradigm, yet if the language supported/proposed such a syntax,
programmers would start to re-arrange the whole object hierarchy in a
new, more modular and universal way.

mark

Mark Janssen

unread,
Mar 18, 2013, 12:26:41 AM3/18/13
to Python List, Python-Ideas
Continuing on this thread, there would be a new bunch of behaviors to
be defined. Since "everything is an object", there can now be a
standard way to define the *next* common abstraction of "every object
interacts with other objects". And going with my suggestion of
defining >> and << operators, I'm going to explore the concept
further....

>>> 42 >> MyNumberType #would add the integer to your integer type
>>> 42 >> MyCollectionType #would add the object into your collection: *poof*: no more random syntaxiis for putting things in collections.\
>>> MyObject >> # queries the object to output its state.
>>> "http://www.cnn.com" >> MyInternetObject #outputs the HTML text from CNN's home page.

Each object has to figure out how it will receive things from outside
of it. Things it can't handle (a string sent to an int) just have to
be dropped to some other space, much like stderr does within the O.S.

There are probably many other very interesting examples, but the key
idea I'm working on (as noted in other messages), is a sort-of
universal language for the internet, a WebOS to be applied to a
universal data model.

Mark

Mark Janssen

unread,
Mar 18, 2013, 12:46:26 AM3/18/13
to Python List, Python-Ideas
On Sun, Mar 17, 2013 at 9:26 PM, Mark Janssen <dreamin...@gmail.com> wrote:
> Continuing on this thread, there would be a new bunch of behaviors to
> be defined. Since "everything is an object", there can now be a
> standard way to define the *next* common abstraction of "every object
> interacts with other objects". And going with my suggestion of
> defining >> and << operators, I'm going to explore the concept
> further....
> Each object has to figure out how it will receive things from outside
> of it. Things it can't handle (a string sent to an int) just have to
> be dropped to some other space, much like stderr does within the O.S.

I guess here's the idea I'm getting at. As a programming language
paradigm, OOP has to evolve -- it still has too much dependency on
number-crunching and the mathematical operators still dominate.

But a better abstraction to wrap the OOP paradigm around is
*message-passing* rather than *arithmetic*. And having in/out
operators on objects is just *way cool*.

mark

Steven D'Aprano

unread,
Mar 18, 2013, 2:46:32 AM3/18/13
to python...@python.org
On 18/03/13 14:53, Mark Janssen wrote:
> Hello,
>
> I just posted an answers on quora.com about OOP (http://qr.ae/TM1Vb)
> and wanted to engage the python community on the subject.
>
> Alan Kay's idea of message-passing in Smalltalk are interesting, and
> like the questioner says, never took off. My answer was that Alan
> Kay's abstraction of "Everything is an object" fails because you can't
> have message-passing, an I/O task, working in the same space as your
> objects -- they are two very different functionalities and they have
> to be preserved **for the programmer**.
>
> This functional separation made me think that Python could benefit
> from a syntactical, language-given separation between Classes and the
> messages between them, to encourage loosely-coupled, modular OOP.
> Something that OOP has always promised but never delivered.


I am very interested in this as a concept, although I must admit I'm not entirely sure what you mean by it. I've read your comment on the link above, and subsequent emails in this thread, and I'm afraid I don't understand what you mean here. I feel you are assuming that your readers are already experts on message-passing languages (Smalltalk?). I know what *I* mean by message passing, but that's not necessarily what you mean by it.

For example, you state in another email:

[quote]
By building it into the language, it would *enforce* a modular object
style, rather than the current, very specialized and very programmer
specific way there is now. In fact, most people never really think in
that paradigm, yet if the language supported/proposed such a syntax,
programmers would start to re-arrange the whole object hierarchy in a
new, more modular and universal way.
[end quote]

I don't understand this. In what way would message passing enforce a modular object style? In what way does Python not already have a modular object style?



--
Steven

Chris Angelico

unread,
Mar 18, 2013, 2:58:50 AM3/18/13
to python-ideas
On Mon, Mar 18, 2013 at 3:46 PM, Mark Janssen <dreamin...@gmail.com> wrote:
> I guess here's the idea I'm getting at. As a programming language
> paradigm, OOP has to evolve -- it still has too much dependency on
> number-crunching and the mathematical operators still dominate.
>
> But a better abstraction to wrap the OOP paradigm around is
> *message-passing* rather than *arithmetic*. And having in/out
> operators on objects is just *way cool*.

"Way cool", unfortunately, isn't enough for writing code. It has to be
useful, too. The Zen of Python reminds us that practicality beats
purity; turning everything into message passing may be awesome in
purity, but where does it stand on practicality? Are there real-world
problems that are awkward to solve in present-day Python that are made
massively cleaner/easier with this proposal?

I suppose what I'm asking for is a 1-2 sentence blurb to sell the
idea. What's the key advantage for daily work?

ChrisA

Yuval Greenfield

unread,
Mar 18, 2013, 3:23:11 AM3/18/13
to Chris Angelico, python-ideas
On Mon, Mar 18, 2013 at 8:58 AM, Chris Angelico <ros...@gmail.com> wrote:
I suppose what I'm asking for is a 1-2 sentence blurb to sell the
idea. What's the key advantage for daily work?


In Erlang, message passing between processes is the main/only thing you do. When every program is built as a set of processes passing messages, you get free parallelization. You can also arrange the message queuing to allow hot-replacing processes, i.e. update your code while it's running.

It's a neat concept, but it's not in python's history or culture to "enforce" programming paradigms. And of course the bit shifting operators aren't going anywhere.


Yuval Greenfield

Greg Ewing

unread,
Mar 18, 2013, 1:34:37 AM3/18/13
to Python-Ideas
Ian Cordasco wrote:
> On Sun, Mar 17, 2013 at 11:53 PM, Mark Janssen
> <dreamin...@gmail.com> wrote:
>
>>Hello,
>>
>>I just posted an answers on quora.com about OOP (http://qr.ae/TM1Vb)
>>and wanted to engage the python community on the subject.

My answer to that question would be that it *did*
catch on, it's just that we changed the terminology.
Instead of message passing, we talk about calling
methods.

IMO the term "message passing" in Smalltalk is
misleading, because it suggests there is something
asynchronous going on, but there isn't. It's just
a subroutine call.

--
Greg

Masklinn

unread,
Mar 18, 2013, 3:47:51 AM3/18/13
to python-ideas

On 2013-03-18, at 06:34 , Greg Ewing wrote:

> Ian Cordasco wrote:
>> On Sun, Mar 17, 2013 at 11:53 PM, Mark Janssen
>> <dreamin...@gmail.com> wrote:
>>> Hello,
>>>
>>> I just posted an answers on quora.com about OOP (http://qr.ae/TM1Vb)
>>> and wanted to engage the python community on the subject.
>
> My answer to that question would be that it *did*
> catch on, it's just that we changed the terminology.
> Instead of message passing, we talk about calling
> methods.

Ruby uses a smalltalk-ish terminology: message is what is sent to an
other object, method is a hook used by an object to respond to a
message. Hence `Object#send`[0] and the lack of externally-accessible
attributes (unless explicitly exposed via a message). I believe
objective-c is much the same, for similar reasons (and thus the
low-level routine for message dispatching is objc_msgSend()[1])

[0] http://ruby-doc.org/core-2.0/Object.html#method-i-send
[1] https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/objc_msgSend

Shane Green

unread,
Mar 18, 2013, 4:51:38 AM3/18/13
to Mark Janssen, Python List, Python-Ideas
So, by introducing this collaboration mechanism with a syntax that defines it as sending and receiving things that are *not* arbitrary objects, the language would naturally reinforce a more thoroughly decoupled architecture?

Sent from my iPad

Mark Janssen

unread,
Mar 18, 2013, 12:55:05 PM3/18/13
to Steven D'Aprano, python...@python.org
On Sun, Mar 17, 2013 at 11:46 PM, Steven D'Aprano <st...@pearwood.info> wrote:
> I am very interested in this as a concept, although I must admit I'm not
> entirely sure what you mean by it. I've read your comment on the link above,
> and subsequent emails in this thread, and I'm afraid I don't understand what
> you mean here. I feel you are assuming that your readers are already experts
> on message-passing languages (Smalltalk?). I know what *I* mean by message
> passing, but that's not necessarily what you mean by it.

I'm sorry, I haven't been very clear. I'm not even an expert on
message-passing languages, but I see that it's a profound concept that
hasn't been adequately integrated into the OOP model. In any case, I
will try to do better. And I apologize to everyone on the list for
the prior mail spam. A part of me is a bit giddy with the idea.

By message passing, I mean all the ways we communicate to objects in
the OOP environment. Usually we "communicate" to them through
method-invokation. But this is the wrong way, I argue, to look at the
problem.

With function or method syntax, you're telling the computer to
"execute something", but that is not the right concepts for OOP. You
want the objects to interact with each other and in a high-level
language, the syntax should assist with that.

> By building it into the language, it would *enforce* a modular object
> style, rather than the current, very specialized and very programmer
> specific way there is now. In fact, most people never really think in
> that paradigm, yet if the language supported/proposed such a syntax,
> programmers would start to re-arrange the whole object hierarchy in a
> new, more modular and universal way.
> [end quote]
>
> I don't understand this. In what way would message passing enforce a modular
> object style? In what way does Python not already have a modular object
> style?

Hopefully my paragraph clarifies that a bit. But the key conceptual
shift is that by enforcing a syntax that moves away from invoking
methods and move to message passing between objects, you're
automatically enforcing a more modular approach.

Mark

Mark Janssen

unread,
Mar 18, 2013, 1:04:36 PM3/18/13
to Python List, Python-Ideas

Antoine Pitrou

unread,
Mar 18, 2013, 1:13:40 PM3/18/13
to python...@python.org, pytho...@python.org
Le Mon, 18 Mar 2013 10:04:36 -0700,
Mark Janssen <dreamin...@gmail.com>
a écrit :

> By message passing, I mean all the ways we communicate to objects in
> the OOP environment. Usually we "communicate" to them through
> method-invokation. But this is the wrong way, I argue, to look at the
> problem.

I think you have failed to articulate clearly what the problem is.

> Hopefully my paragraph clarifies that a bit. But the key conceptual
> shift is that by enforcing a syntax that moves away from invoking
> methods and move to message passing between objects, you're
> automatically enforcing a more modular approach.

That sounds like wishful thinking to me.

Regards

Antoine.

Mark Janssen

unread,
Mar 18, 2013, 1:18:53 PM3/18/13
to Python List, Python-Ideas
> Ian Cordasco wrote:
>>
>> On Sun, Mar 17, 2013 at 11:53 PM, Mark Janssen
>> <dreamin...@gmail.com> wrote:
>>
>>> Hello,
>>>
>>> I just posted an answers on quora.com about OOP (http://qr.ae/TM1Vb)
>>> and wanted to engage the python community on the subject.
>
>
> My answer to that question would be that it *did*
> catch on, it's just that we changed the terminology.
> Instead of message passing, we talk about calling
> methods.

Yes, but this is where it breaks the OOP abstraction by 90 degrees.
By using function calls, you're telling the machine to do something.
But when you want to pass something to an object there should be a
natural way to do this for every object. By using methods you pollute
the concept space with all sorts of semi-random (i.e. personal) names,
like append, add, enqueue, etc.

This proposal would not only make a consistent syntax across all
objects, but train the programmer to *think* modularly in the sense of
having a community of re-usable object. I.e. "What should I do if
another object passes me something?". No one thinks this now, because
the programmer expects new developers to learn *their* interface!

Mark

Mark Janssen

unread,
Mar 18, 2013, 1:36:50 PM3/18/13
to Chris Angelico, python-ideas
>> I guess here's the idea I'm getting at. As a programming language
>> paradigm, OOP has to evolve -- it still has too much dependency on
>> number-crunching and the mathematical operators still dominate.
>>
>> But a better abstraction to wrap the OOP paradigm around is
>> *message-passing* rather than *arithmetic*. And having in/out
>> operators on objects is just *way cool*.
>
> "Way cool", unfortunately, isn't enough for writing code. It has to be
> useful, too. The Zen of Python reminds us that practicality beats
> purity; turning everything into message passing may be awesome in
> purity, but where does it stand on practicality? Are there real-world
> problems that are awkward to solve in present-day Python that are made
> massively cleaner/easier with this proposal?

Perhaps I'm using the wrong language. Instead of borrowing from Alan
Kays, it should be called "data passing". It's a very common and
important part of the object-oriented paradigm. The language could
support a *consistent* way to do this for all objects.

> I suppose what I'm asking for is a 1-2 sentence blurb to sell the
> idea. What's the key advantage for daily work?

No more having to learn each programers interface for passing
interacting with the object. The >> and << syntax now becomes the de
facto way for object interaction across all objects. Class design
will revolve around this fact.

Mark

Rob Cliffe

unread,
Mar 18, 2013, 1:44:00 PM3/18/13
to python...@python.org
I'm struggling to understand what you mean (and I don't seem to be the
only one).
As far as I can tell, you would replace an object with N methods by an
object with one huge method (ProcessReceivedMessage say) which deals
with N cases.
(Not an improvement as your code has become much less modular.)
And instead of semi-arbitrary method names, you have semi-arbitrary
messages (names, numbers or whatever).
Just as much of an interface to learn.
Am I missing something?
Can you give a semi-concrete example using pseudo-code, where your way
clearly does something which can't be done as well (or at all) using
method calls?
Rob Cliffe

Mark Janssen

unread,
Mar 18, 2013, 1:54:12 PM3/18/13
to Rob Cliffe, python...@python.org
>>> My answer to that question would be that it *did*
>>> catch on, it's just that we changed the terminology.
>>> Instead of message passing, we talk about calling
>>> methods.
>>
>> Yes, but this is where it breaks the OOP abstraction by 90 degrees.
>> By using function calls, you're telling the machine to do something.
>> But when you want to pass something to an object there should be a
>> natural way to do this for every object. By using methods you pollute
>> the concept space with all sorts of semi-random (i.e. personal) names,
>> like append, add, enqueue, etc.
>>
>> This proposal would not only make a consistent syntax across all
>> objects, but train the programmer to *think* modularly in the sense of
>> having a community of re-usable object. I.e. "What should I do if
>> another object passes me something?". No one thinks this now, because
>> the programmer expects new developers to learn *their* interface!

> I'm struggling to understand what you mean (and I don't seem to be the only
> one).
> As far as I can tell, you would replace an object with N methods by an
> object with one huge method (ProcessReceivedMessage say) which deals with N
> cases.
> (Not an improvement as your code has become much less modular.)

No. If the language provides a data-passing syntax (like << and >>),
then programmers would design their object hierarchy with this idea in
mind. If you have N methods (N > 1) for passing data to an object,
I'm suggesting you haven't designed you object classes properly.

> And instead of semi-arbitrary method names, you have semi-arbitrary messages
> (names, numbers or whatever).
> Just as much of an interface to learn.
> Am I missing something?

Yes, the data passing syntax (<< and >>) would be the same for all
objects because the language itself would be providing the primary
interface between objects.

> Can you give a semi-concrete example using pseudo-code, where your way
> clearly does something which can't be done as well (or at all) using method
> calls?

I will work on it. What I'd really like is to refactor all the Python
standard library code to see how much simpler it would be.

Ethan Furman

unread,
Mar 18, 2013, 1:47:33 PM3/18/13
to Python-Ideas
On 03/18/2013 10:36 AM, Mark Janssen wrote:
> No more having to learn each programers interface for passing
> interacting with the object. The >> and << syntax now becomes the de
> facto way for object interaction across all objects. Class design
> will revolve around this fact.

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?

--
~Ethan~

Mark Janssen

unread,
Mar 18, 2013, 2:22:29 PM3/18/13
to Ethan Furman, Python-Ideas
On Mon, Mar 18, 2013 at 10:47 AM, Ethan Furman <et...@stoneleaf.us> wrote:
> On 03/18/2013 10:36 AM, Mark Janssen wrote:
>>
>> No more having to learn each programers interface for passing
>> interacting with the object. The >> and << syntax now becomes the de
>> facto way for object interaction across all objects. Class design
>> will revolve around this fact.
>
> 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).

I suggest that the mathematical domain is completely separate from
what most people do with computers and with programming. The term
"computers" is a misnomer, and is misinforming the power that the
computer as an *abstraction* provides. Keep in mind that there aren't
really 1's and 0's moving around in the machine. In the machine,
there are only *states* (which could *any* differentiable "thing",
like "happy face" "sad face"). We've just come to symbolize them with
numbers because of their history of calculation.

Let's examine arithmetic for a moment. Ultimately, arithmetic can be
done with simple + and - operators (multiplication simply by repeating
addition, etc). If you allow negative numbers you really only need
the ONE operator. Now, I think numbers are the only domain where the
more standard (current) interface should be preserved, but yet, as
I've shown, the message or data-passing interface can accommodate
arithmetic if purity is desired, it's just that for real math, it
won't be as efficient.

But that's okay, because really, what we're generally doing (i mean
the computers) these days is manipulating *symbols* or "objects".
Most of the time that is what we're doing -- not arithmetic, except in
some very simple ways which I will try to elucidate. So, *if* that is
the case, then the language should develop a *construct* in which to
standardize this fact.

So, if our domain is "objects" more than number (which is a pretty
concrete thing), then, in what ways do (or should) numbers and
data/symbols/objects interact within the programming domain or
environment? As you know from C, most interaction with number *as a
language construct* was fairly limited: incrementing a loop, for
example. In fact C invented the unit increment as a syntactical
element. I think this is the more valid way of examining an interface
into number as a linguistic construction.

But as I told another poster, I will examine the standard library and
come up with some good examples of how a standardized data passing
interface will benefit the programmer.

Mark

Joao S. O. Bueno

unread,
Mar 18, 2013, 3:15:59 PM3/18/13
to Mark Janssen, Python-Ideas
On 18 March 2013 15:22, Mark Janssen <dreamin...@gmail.com> wrote:
> But as I told another poster, I will examine the standard library and
> come up with some good examples of how a standardized data passing
> interface will benefit the programmer.


Before you go into that length maybe you could tell us, for example,
if we have an image object in a 3rd party library
and we want to draw a rectangle. Currently I write something like:

>>> myimage.draw_rect((x1,y1,width, height), RED)

Now, if I want to save this image to a file:

>>> myimage.save("myfile.png")

--
So, how would these two simple examples be rewritten in such a magic
message-only World?


js
-><-

Georg Brandl

unread,
Mar 18, 2013, 3:06:33 PM3/18/13
to python...@python.org, pytho...@python.org
Am 18.03.2013 05:26, schrieb Mark Janssen:
> Continuing on this thread, there would be a new bunch of behaviors to
> be defined. Since "everything is an object", there can now be a
> standard way to define the *next* common abstraction of "every object
> interacts with other objects".

The problem is that for most objects there isn't *the* interaction. Sure,
you could split up complicated objects into small pieces with a smaller
functionality, but at some point you have to stop. Let's see how this
concept fares with simple types such as integers or collections...

> And going with my suggestion of
> defining >> and << operators, I'm going to explore the concept
> further....
>
>>>> 42 >> MyNumberType #would add the integer to your integer type

That's just random. Why not multiply? Why not exponentiate?

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

So you've replaced one method of a collections API by your magical operator,
for all collections. What about the other methods that are just as important,
such as deleting items, indexing, and querying? The "syntaxitis" would stay
just the same, except if you introduce more operators, which means new syntax
again.

Also, how would this work for dictionaries or deques?

>>>> MyObject >> # queries the object to output its state.

What is "its state"? A readable representation? A serialized representation?
A memory dump?

>>>> "http://www.cnn.com" >> MyInternetObject #outputs the HTML text from CNN's home page.
>
> Each object has to figure out how it will receive things from outside
> of it. Things it can't handle (a string sent to an int) just have to
> be dropped to some other space, much like stderr does within the O.S.
>
> There are probably many other very interesting examples, but the key
> idea I'm working on (as noted in other messages), is a sort-of
> universal language for the internet, a WebOS to be applied to a
> universal data model.

It seems that you are reinventing pipes (such as UNIX shell pipes).
I agree that as a model for handling data the pipe paradigm is elegant,
but only as long as you deal with simple data of a single kind (such as
strings in the UNIX world). But make the data complex enough, and it's
an instance "all problems look like pipes if all you have is a vertical
bar".

Georg

Masklinn

unread,
Mar 18, 2013, 3:52:06 PM3/18/13
to python-ideas
On 2013-03-18, at 20:06 , Georg Brandl wrote:
>
>>>>> "http://www.cnn.com" >> MyInternetObject #outputs the HTML text from CNN's home page.
>>
>> Each object has to figure out how it will receive things from outside
>> of it. Things it can't handle (a string sent to an int) just have to
>> be dropped to some other space, much like stderr does within the O.S.
>>
>> There are probably many other very interesting examples, but the key
>> idea I'm working on (as noted in other messages), is a sort-of
>> universal language for the internet, a WebOS to be applied to a
>> universal data model.
>
> It seems that you are reinventing pipes (such as UNIX shell pipes).
> I agree that as a model for handling data the pipe paradigm is elegant,
> but only as long as you deal with simple data of a single kind (such as
> strings in the UNIX world). But make the data complex enough, and it's
> an instance "all problems look like pipes if all you have is a vertical
> bar".

Or you start tagging your messages (since the messages are apparently
structured not byte-streams as they are with unix pipes) as is done in
Erlang, the end-result mostly being to remove a (useful) bit of syntactic
sugar. Unless the messages become asynchronous, then I guess you get
actors?

Andrew Barnert

unread,
Mar 18, 2013, 4:19:19 PM3/18/13
to Mark Janssen, Ethan Furman, Python-Ideas
From: Mark Janssen <dreamin...@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.

Mark Janssen

unread,
Mar 18, 2013, 4:24:49 PM3/18/13
to Georg Brandl, pytho...@python.org, python...@python.org
On Mon, Mar 18, 2013 at 12:06 PM, Georg Brandl <g.br...@gmx.net> wrote:
> Am 18.03.2013 05:26, schrieb Mark Janssen:
>> Continuing on this thread, there would be a new bunch of behaviors to
>> be defined. Since "everything is an object", there can now be a
>> standard way to define the *next* common abstraction of "every object
>> interacts with other objects".
>
> The problem is that for most objects there isn't *the* interaction. Sure,
> you could split up complicated objects into small pieces with a smaller
> functionality, but at some point you have to stop.

Yes. But that is the point, if you look at the quora post -- to
invert the object model and create mashups of simple modular data
types and working *upwards*.

> Let's see how this
> concept fares with simple types such as integers or collections...
>
>>>>> 42 >> MyNumberType #would add the integer to your integer type
>
> That's just random. Why not multiply? Why not exponentiate?

Well, as I noted in another post, that while these can be broken down
into their simpler component (addition and negative numbers), numbers
should probably be treated separately.

>>>>> 42 >> MyCollectionType #would add the object into your collection:
>> *poof*: no more random syntaxiis for putting things in collections.\
>
> So you've replaced one method of a collections API by your magical operator,
> for all collections.

Yes -- for all collections. That's a pretty big gain right?

> What about the other methods that are just as important,
> such as deleting items, indexing, and querying? The "syntaxitis" would stay
> just the same, except if you introduce more operators, which means new syntax
> again.
>
> Also, how would this work for dictionaries or deques?

Well, now you get into the Work: a unified data model. Deques,
trees, lists, etc were all preliminary evolutionary explorations on
this giant computer science journey of knowledge (and data types)
which will have to be, can be, pruned and dropped.

>>>>> MyObject >> # queries the object to output its state.
>
> What is "its state"? A readable representation? A serialized representation?
> A memory dump?

That's still for us to decide. We're mastering the OOP paradigm here:
What is the ideal object and what is "in common" across all objects?
We are Zen, we want to master the notion of object. What is the
simplest object model possible without sacrificing critical
functionality...

>>>>> "http://www.cnn.com" >> MyInternetObject #outputs the HTML text from CNN's home page.
>>
>> Each object has to figure out how it will receive things from outside
>> of it. Things it can't handle (a string sent to an int) just have to
>> be dropped to some other space, much like stderr does within the O.S.
>>
>> There are probably many other very interesting examples, but the key
>> idea I'm working on (as noted in other messages), is a sort-of
>> universal language for the internet, a WebOS to be applied to a
>> universal data model.
>
> It seems that you are reinventing pipes (such as UNIX shell pipes).

That is a very interesting comparison. That is something like what
I'm trying to do. In tandem with the Internet, I do see a kind of
synthesis of Web + O.S. integration -- ultimately, creating a "data
ecosystem".

mark

Mark Janssen

unread,
Mar 18, 2013, 4:42:46 PM3/18/13
to Andrew Barnert, Python-Ideas
> 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:
[...snipped several pages...]

All that is very good analysis. However, these data types you talk
about, I'm gong to argue are explorations from the journey of computer
*science* which are suboptimal. But to say suboptimal I have to
suggest the context in which I'm optimizing. That context is creating
the idea of a data universe and ecosystem where the ideals of OOP and
re-usability come out of dreamland and into reality. And the only way
to do that is to start at the *bottom* and work upwards. That is to
define the fundamental unit, to re-evalutate the fundamental Object.
But to figure out that you need also the fundamental communications
pathway -- how those fundamental objects will interact.

The questions for this data universe can be boiled down to only a few:
what event necessitates the object/node creation? What is the
relationship *between* objects?

At least that's the start of what I'm calling a unified data model.

Mark

Andrew Barnert

unread,
Mar 18, 2013, 5:26:07 PM3/18/13
to Mark Janssen, Python-Ideas
From: Mark Janssen <dreamin...@gmail.com>

Sent: Monday, March 18, 2013 1:42 PM


>
>> 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? 

> All that is very good analysis.  However, these data types you talk


> about, I'm gong to argue are explorations from the journey of computer
> *science* which are suboptimal.

I chose these data types because they were your own example.

> But to say suboptimal I have to

> suggest the context in which I'm optimizing.  That context is creating
> the idea of a data universe and ecosystem where the ideals of OOP and
> re-usability come out of dreamland and into reality.  And the only way
> to do that is to start at the *bottom* and work upwards.  That is to
> define the fundamental unit, to re-evalutate the fundamental Object.
> But to figure out that you need also the fundamental communications
> pathway -- how those fundamental objects will interact.
>
> The questions for this data universe can be boiled down to only a few:
> what event necessitates the object/node creation?  What is the
> relationship *between* objects?


OK, so "computer science" data types like lists, and integers (as things you can perform both multiplication and addition on), are not fundamental. What is fundamental?

Anyone who knows any mathematical logic can answer this. For example, give me the empty set and a handful of fundamental operations, and I can give you integers (starting with Peano arithmetic) and lists (starting with ordered pairs). Or, give me relations and a handful of fundamental operations. Or…

The problem here is that "handful of fundamental operations". You want just _one_ fundamental binary operation. Well, even that's possible. In fact, you can use the X combinator as both your basic value and your one basic operation.

Even if you _do_ reduce everything to the X combinator, that still doesn't explain how "42 >> mycollection" fails to be ambiguous. There are multiple ways you can model integers and collections that are all perfectly sensible, one of which will make "42 >> mylist" append 42 to the end of the list, one of which will make "42 >> mylist" append to the start, and one of which will make "42 >> mylist" insert the next argument to come in at position 42. Which one of these is "right"? And, if you don't like that type (which, again, was your suggestion), pick any other type that anyone might ever want to deal with.

And this goes back to the same fundamental misconception that I pointed out in the last email, that you skipped over. Smalltalk and Simula, and their descendants, and relational databases, and semantic web initiatives, and so on all have some concept of structure to their messages. This is what allows the same object to do more than one thing. That's why they can model fields and sequences, cars and phones, web services and documents, etc. That's why they're useful.

Finally, if you want to design a whole new language from the ground up, whether on top of the X combinator or ER models or RDF+RIF or whatever, with a completely different model from Python and a completely different syntax… why would you post about it on python-ideas?

Mark Janssen

unread,
Mar 18, 2013, 5:37:30 PM3/18/13
to Andrew Barnert, Python-Ideas
>> All that is very good analysis. However, these data types you talk
>> about, I'm gong to argue are explorations from the journey of computer
>> *science* which are suboptimal.
>
> I chose these data types because they were your own example.
>
>> The questions for this data universe can be boiled down to only a few:
>> what event necessitates the object/node creation? What is the
>> relationship *between* objects?
>
> OK, so "computer science" data types like lists, and integers (as things you can perform both multiplication and addition on), are not fundamental. What is fundamental?
>
> Anyone who knows any mathematical logic can answer this. For example, give me the empty set and a handful of fundamental operations, and I can give you integers (starting with Peano arithmetic) and lists (starting with ordered pairs). Or, give me relations and a handful of fundamental operations. Or…

Yes, but then you're working in the abstraction space I call the
Aperion (after the Greeks), but this is to create a different space,
with a different set of basis. You're working with lines. I'm
working with data. This is important if you're going make such
comparisons.

> And this goes back to the same fundamental misconception that I pointed out in the last email, that you skipped over. Smalltalk and Simula, and their descendants, and relational databases, and semantic web initiatives, and so on all have some concept of structure to their messages. This is what allows the same object to do more than one thing.

Well, I'm going to suggest that those initiatives failed because of
their fundamental premise is flawed.

> Finally, if you want to design a whole new language from the ground up,

Whoa whoa -- I'm not trying to design a "whole new language". I'm
trying to continue the evolution of programming language elegance.
And to me Python is the right direction.

Mark
Message has been deleted

Mark Janssen

unread,
Mar 18, 2013, 7:41:41 PM3/18/13
to Andrew Barnert, Python List, Python-Ideas
On Mon, Mar 18, 2013 at 2:51 PM, Andrew Barnert <abar...@yahoo.com> wrote:
> Have you even looked at a message-passing language?
>
> A Smalltalk "message" is a selector and a sequence of arguments. That's what you send around. Newer dynamic-typed message-passing OO and actor languages are basically the same as Smalltalk.

Yes, but you have to understand that Alan Kays came with strange ideas
of some future computer-human symbiosis. So his language design and
other similar attempts (like php) is rather skewed from that premise

And also, despite name-dropping, I'm not trying to create anything
like that idea of message-passing. I'm talking about something very
simple, a basic and universal way for objects to communicate.

>> With function or method syntax, you're telling the computer to
>> "execute something", but that is not the right concepts for OOP. You
>> want the objects to interact with each other and in a high-level
>> language, the syntax should assist with that.
>
> And you have to tell the object _how_ to interact with each other.

This is a different paradigm that what I'm talking about. In the OOP
of my world, Objects already embody the intelligence of how they are
going to interact with the outside world, because I put them there.

> Even with reasonably intelligent animals, you don't just tell two animals to interact, except in the rare case where you don't care whether they become friends or dinner.

You're model of computer programming is very alien to me. So I don't
think it will be productive to try to convince you of what I'm
suggesting, but feel free to continue...

Steven D'Aprano

unread,
Mar 18, 2013, 8:39:05 PM3/18/13
to python...@python.org
On 19/03/13 07:24, Mark Janssen wrote:

>>>>>> 42 >> MyCollectionType #would add the object into your collection:
>>> >> *poof*: no more random syntaxiis for putting things in collections.\
>> >
>> >So you've replaced one method of a collections API by your magical operator,
>> >for all collections.
> Yes -- for all collections. That's a pretty big gain right?


No, not at all. If it's a gain at all, it's a tiny, microscopic gain. But it's not a gain. We lose a lot:

- we can no longer distinguish between *adding* something to an unordered collection, and *appending* to an ordered collection;

- 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.

- 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.


But please don't let me discourage you. I am actually very interested in a message passing idiom, I just don't think that it is as big a fundamental paradigm shift as you appear to believe. Way back in the late 1980s, I spent a lot of time working with a language that used a message passing paradigm, Apple's Hypertalk (part of Hypercard, which was strongly influenced by Alan Kay and Smalltalk). Hypertalk is long gone now, but you can get a feel for it with something like OpenXION:

http://www.openxion.org

I encourage you to see how message passing paradigms operate in existing other languages, such as OpenXION, and to come up with examples of syntax for simple tasks. E.g. what syntax would you use for something like this?

* Get a file name from the user.
* Open a file with that name.
* Read the text of that file.
* Convert the text to lowercase.
* Write it back out to the same file.


At the moment, I couldn't even begin to imagine how I might write that code using your syntax, let alone how it would be an improvement.



--
Steven

Mark Janssen

unread,
Mar 18, 2013, 9:38:49 PM3/18/13
to Steven D'Aprano, python...@python.org
On Mon, Mar 18, 2013 at 5:39 PM, Steven D'Aprano <st...@pearwood.info> wrote:
>>> >So you've replaced one method of a collections API by your magical
>>> > operator,
>>> >for all collections.
>>
>> Yes -- for all collections. That's a pretty big gain right?
>
> No, not at all. If it's a gain at all, it's a tiny, microscopic gain. But
> it's not a gain. We lose a lot:
>
> - 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. Even 15 years of python append and extend are still
ambiguous and confusing. You've adapted to this.

> - 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.

> - 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.

> E.g. what syntax would you use for something like this? [...]

Keeping in mind, this idea would require a major refactoring of the
standard library. Instead of these very ornate (byzantine?) complex
classes, we have many smaller, more universal/general classes,
building up to the complexity desired (like Unix pipes did for shell
scripting, files, and the O.S.). Those "universals" haven't been
conceived yet for Python, so I don't know yet what it will look like.

> * Open a file with that name.

Why does everyone seem to pick the most corner-type cases? As this is
about a "universal data model", issues with interacting within the
existing operating system becomes an issue and has to be specially
handled. So you have to ask how deep you want me to go in this
architectural model I'm envisioning, because as it is a universal
model, ultimately the O.S. changes radically (which is why I was
suggesting that the issue of Python async behavior be postponed).

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.

Mark

Mark Lawrence

unread,
Mar 18, 2013, 10:09:28 PM3/18/13
to python...@python.org
On 19/03/2013 01:38, Mark Janssen wrote:

+1 best trolling so far this millenium.

--
Cheers.

Mark Lawrence

Haoyi Li

unread,
Mar 18, 2013, 10:14:32 PM3/18/13
to Mark Janssen, python-ideas
I felt I just had to chip in here, knowing something about how actors (which is basically what you're advocating) work in Scala. Some points:

- Message sends have to give you something that method calls don't

Whether that's the ability to ignore not-understood messages (like in Obj-C), or making the message send-receive behavior asynchronous (like in Scala) or ensuring messages are handled serially per-object, it has to be something. Message sends which don't provide anything over method calls are really just method calls with a funky syntax.

As such, in Scala actors are used when you need these benefits: stateful, mutable objects which are accessed from multiple threads but have non-thread-safe innards, or objects whose allowed behavior changes over time and the "ignore not-understood messages" thing comes in handy. 

Worker/connection pools, state-machines, that sort of thing. Nobody sends messages to integers or lists!

- Actors (or message-based objects) work in tandem with case classes (data-based objects/structs) and don't replace them.

I think this is a significant point: small things (lists, tuples, primitives) are kept as structs and the data inside them is manipulated directly, and big things (web servers, background-workers, http clients) are then done with state-hiding and encapsulation and all that. 

Having a simple thing (like a list or a tuple) with encapsulation and sending messages to it is as silly as having a massive structure with all its internal structures and data exposed to the outside world.

In particular, your dislike for "lists within lists" seems incompatible with your desire for "more universal/general classes, building up to the complexity desired". Isn't that almost the perfect example of simple, general classes used to build up complex structures?


That's all for now
-Haoyi



alex23

unread,
Mar 18, 2013, 10:25:39 PM3/18/13
to python...@python.org
On Mar 19, 6:24 am, Mark Janssen <dreamingforw...@gmail.com> wrote:
> Well, now you get into the Work:  a unified data model.   Deques,
> trees, lists, etc were all preliminary evolutionary explorations on
> this giant computer science journey of knowledge (and data types)
> which will have to be, can be, pruned and dropped.

These data types weren't created because of any ad hoc "exploration"
of best practice. They all have different performance & memory
characteristics. What type you use for a particular problem is
directly related to the requirements. How do you plan on having a
unified data model that provides optimal performance / memory usage
for every problem space?

Something more concrete than "evolving the language" wankery - like
actual, non-trivial examples - would really help with your argument.

Andrew Barnert

unread,
Mar 18, 2013, 11:12:41 PM3/18/13
to Mark Janssen, Steven D'Aprano, python...@python.org
> From: Mark Janssen <dreamin...@gmail.com>

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


> On Mon, Mar 18, 2013 at 5:39 PM, Steven D'Aprano <st...@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.

Andrew Barnert

unread,
Mar 18, 2013, 11:31:31 PM3/18/13
to Mark Janssen, Python List, Python-Ideas
From: Mark Janssen <dreamin...@gmail.com>

Sent: Monday, March 18, 2013 4:41 PM


> On Mon, Mar 18, 2013 at 2:51 PM, Andrew Barnert <abar...@yahoo.com>
> wrote:
>> Have you even looked at a message-passing language?
>>
>> A Smalltalk "message" is a selector and a sequence of arguments.
> That's what you send around. Newer dynamic-typed message-passing OO and
> actor languages are basically the same as Smalltalk.
>
> Yes, but you have to understand that Alan Kays came with strange ideas
> of some future computer-human symbiosis.  So his language design and
> other similar attempts (like php) is rather skewed from that premise

The idea that message passing is fundamentally different from method calling also turned out to be one of those strange ideas, since it only took a couple years to prove that they are theoretically completely isomorphic—and, for that matter, they're both isomorphic to closures.

> And also, despite name-dropping, I'm not trying to create anything
> like that idea of message-passing.  I'm talking about something very
> simple, a basic and universal way for objects to communicate.

Message passing is a simple, basic, and universal way for objects to communicate. Everything from dot-syntax method calls to JSON RPC protocols can be modeled as passing messages. But what you're talking about isn't message passing. The idea that messages have names, and reference objects as arguments, is fundamental, and by leaving that out, you're talking about something different. 

In effect, your "objects" are just single-parameter functions, and your "messages" are the call operator.

>>> With function or method syntax, you're telling the computer to
>>> "execute something", but that is not the right concepts for
> OOP.  You
>>> want the objects to interact with each other and in a high-level
>>> language, the syntax should assist with that.
>> 

>> And you have to tell the object _how_ to interact with each other.
>
> This is a different paradigm that what I'm talking about.  In the OOP
> of my world, Objects already embody the intelligence of how they are
> going to interact with the outside world, because I put them there.

The paradigm you're talking about is useless. You have lists that know how to append, but don't know how to get/search/iterate. Almost every useful object needs the intelligence to interact with the world in two or more ways.

>> Even with reasonably intelligent animals, you don't just tell two
> animals to interact, except in the rare case where you don't care whether
> they become friends or dinner.
>
> You're model of computer programming is very alien to me.  So I don't
> think it will be productive to try to convince you of what I'm
> suggesting, but feel free to continue...


My model of (object-oriented) computer programming is that programming objects model objects which have a variety of behaviors, each of which is triggered by sending a different message. This is pretty much the central definition that everyone who programs or theorizes about programming uses. If you read any textbook, wiki page, journal article, or tutorial, they're all talking about that, or something directly isomorphic to it. If that's alien to you, then object-oriented programming is alien to you.

Chris Angelico

unread,
Mar 19, 2013, 2:28:45 AM3/19/13
to python-ideas
On Tue, Mar 19, 2013 at 12:38 PM, Mark Janssen
<dreamin...@gmail.com> wrote:
> On Mon, Mar 18, 2013 at 5:39 PM, Steven D'Aprano <st...@pearwood.info> wrote:
>>>> >So you've replaced one method of a collections API by your magical
>>>> > operator,
>>>> >for all collections.
>>>
>>> Yes -- for all collections. That's a pretty big gain right?
>>
>> No, not at all. If it's a gain at all, it's a tiny, microscopic gain. But
>> it's not a gain. We lose a lot:
>>
>> - 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. Even 15 years of python append and extend are still
> ambiguous and confusing. You've adapted to this.

There are interfaces where a generic "do something with X and Y"
concept makes sense, but I don't think program code is one of them. In
a GUI, you can drag one icon (#1) onto another icon (#2), which might
accomplish any of the following:

* Move file/folder #1 into folder #2
* Copy file/directory #1 onto remote volume #2
* Print document #1 on printer #2
* Invoke program #2, passing it the name of #1
* Destroy object #1 using the settings of shredder #2
* Send email #1 to recipient #2

These are all actions that I *have done*, and all using the exact same
invocation sequence. It makes sense in context.

With code, though, there are just way too many common operations.
Since we're working at a lower level of objects and data structures,
we're going to need to do a lot more. (Of course, drag-and-drop has a
number of other UI actions possible, such as dragging a file into the
body of a folder - that provides destination AND position, so you
could use that to put something into a particular place in an ordered
collection. Plus you can hold modifier keys while dragging, or in
other ways add information. But it's still far FAR less than code can
do.) How do you identify, to the code, which message you want to pass?
The easiest way is with a keyword... a method name. Which brings us
right back to where heaps of high level languages are: method calling.

ChrisA

Nick Coghlan

unread,
Mar 19, 2013, 10:49:36 AM3/19/13
to Chris Angelico, python-ideas
On Mon, Mar 18, 2013 at 11:28 PM, Chris Angelico <ros...@gmail.com> wrote:
> There are interfaces where a generic "do something with X and Y"
> concept makes sense, but I don't think program code is one of them.

Having finally parsed out what I think the OP is asking for, I have to
disagree. In fact, Guido disagrees as well: he thinks what the OP
wants is so important that he built it into Python from day one.

The notation Python uses to "send a message" to an object is actually
"obj(message)".

This process of sending a message is referred to as "calling". When
you call someone, the message you send is referred to as "the
arguments to the call".

An object accepts messages by defining a method with the special name
"__call__".

When you define this method, you declare the "parameters" you expect
to receive as part of any calls. The process of mapping the sent
arguments to the declared parameters is referred to as "argument
binding".

You can perform the argument binding step without actually making a
call by using the inspect.Signature.bind API in Python 3.3+ (or the
backport of that API to earlier Python versions:
https://pypi.python.org/pypi/funcsigs/)

However, it's also useful to aggregate objects that you can send
messages to into larger collections, along with shared data for those
objects to work with. Python provides a "class" mechanism for this
aggregation step, and in this case the objects which receive messages
and operate on the shared data are referred to as "methods".

To prevent an infinite regress, Python has a particular kind of object
which it inherently knows how to send a message to, rather than
relying on a "__call__" method. This intrinsic message receiver is
referred to as a "function".

Regards,
Nick.

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia

Ethan Furman

unread,
Mar 19, 2013, 11:33:34 AM3/19/13
to python...@python.org
On 03/19/2013 07:49 AM, Nick Coghlan wrote:
> On Mon, Mar 18, 2013 at 11:28 PM, Chris Angelico <ros...@gmail.com> wrote:
>> There are interfaces where a generic "do something with X and Y"
>> concept makes sense, but I don't think program code is one of them.
>
> Having finally parsed out what I think the OP is asking for, I have to
> disagree. In fact, Guido disagrees as well: he thinks what the OP
> wants is so important that he built it into Python from day one.
>
> The notation Python uses to "send a message" to an object is actually
> "obj(message)".

I don't disagree with you, Nick, but I don't think that's what the OP is
looking for, either. Even using call syntax, it seems to me the OP would still
only be sending one type of message, with no arguments, no differentiation,
no choices.

To use the OP's own example:

some_collection(42)

would add 42 to the collection... but we have no say in where, or how. In fact,
using call() notation we have less than the OP's proposal as his proposal has a
one-way in and a one-way out, but an argument-less* call can only provide one of
those two options.

--
~Ethan~

*By argument-less I mean we can only give one thing to call.

Ian Cordasco

unread,
Mar 19, 2013, 11:58:22 AM3/19/13
to Ethan Furman, python-ideas
On Tue, Mar 19, 2013 at 11:33 AM, Ethan Furman <et...@stoneleaf.us> wrote:
> I don't disagree with you, Nick, but I don't think that's what the OP is
> looking for, either. Even using call syntax, it seems to me the OP would
> still
> only be sending one type of message, with no arguments, no differentiation,
> no choices.

I understand OP wants to be able to send anything, but he seems to be
disregarding how << and >> are currently implemented on objects (via
__lshift__ and __rshift__ respectively). Each of those can be made in
a custom fashion by OP (or anyone else) but the question then becomes,
how do you add extra parameters (assuming you want them), i.e., how do
you do:

obj << 4, *extra_args

I think (because I don't have a way of testing it right now) that
you'd get an error for trying to expand extra_args in the creation of
a tuple, regardless of the signature of __lshift__. Even if you didn't
do that, I think python would interpret that as the creation of a
tuple, i.e., the result of obj << 4 with the rest of the arguments.

> To use the OP's own example:
>
> some_collection(42)
>
> would add 42 to the collection... but we have no say in where, or how. In
> fact,
> using call() notation we have less than the OP's proposal as his proposal
> has a
> one-way in and a one-way out, but an argument-less* call can only provide
> one of
> those two options.
>
> --
> ~Ethan~
>
> *By argument-less I mean we can only give one thing to call.

And if we do this with the current implementation of python you can
still only give one thing to call (assuming I'm correct with my above
example). We would have to fundamentally change python and how it
interprets those special cases (again basing the statement on my above
assumptions/intuition). I'm sure in another language I would find this
feature to be interesting or even appreciate it, but I don't think it
is either very pythonic or useful in python. I'm also wondering if
this is just a very well done troll since OP has yet to back any of
his own examples which he thinks others are choosing to make his life
difficult.

Jeff Jenkins

unread,
Mar 19, 2013, 3:41:34 PM3/19/13
to Ian Cordasco, python-ideas
Does __getattribute__ and __call__ basically accomplish this?  You pass a "message name" to an object which it then uses to route to a handler which takes a tuple "message body" to process the message.  It just happens that the syntax is obj.message_name(message, body, parts) instead of using << or >>

Mark Janssen

unread,
Mar 20, 2013, 12:20:57 AM3/20/13
to Nick Coghlan, python-ideas
On Tue, Mar 19, 2013 at 7:49 AM, Nick Coghlan <ncog...@gmail.com> wrote:
> On Mon, Mar 18, 2013 at 11:28 PM, Chris Angelico <ros...@gmail.com> wrote:
>> There are interfaces where a generic "do something with X and Y"
>> concept makes sense, but I don't think program code is one of them.
>
> Having finally parsed out what I think the OP is asking for, I have to
> disagree. In fact, Guido disagrees as well: he thinks what the OP
> wants is so important that he built it into Python from day one.
>
> The notation Python uses to "send a message" to an object is actually
> "obj(message)".

Cheeky comments aside, the problem with this is that it conflates to
fundamental, very different desires: execute and pass-this-message.

While yes in my mind I can think of obj.method(data) as passing data
to my object, *I don't want to do it in my mind*. I want to do it in
the interpreter. That's a big difference, because *other programmers
can't read my mind* and THEY won't know if I'm passing data or
executing a function.

Mark

Mark Janssen

unread,
Mar 20, 2013, 12:24:48 AM3/20/13
to Terry Reedy, pytho...@python.org, python...@python.org
On Tue, Mar 19, 2013 at 1:09 PM, Terry Reedy <tjr...@udel.edu> wrote:
> On 3/18/2013 11:31 PM, Andrew Barnert wrote:
>
>> The idea that message passing is fundamentally different from method
>> calling also turned out to be one of those strange ideas, since it
>> only took a couple years to prove that they are theoretically
>> completely isomorphic—and,
>
> Since the isomorphism is so obvious, I somehow missed that Kay actually
> thought that they were different. I suppose one could have different (but
> isomorphic) mental image models.

Yes, that's the point I'm making, and it's significant because other
programmers can't see other's mental models.

mark

Mark Janssen

unread,
Mar 20, 2013, 12:36:16 AM3/20/13
to Haoyi Li, python-ideas
On Mon, Mar 18, 2013 at 7:14 PM, Haoyi Li <haoy...@gmail.com> wrote:
> I felt I just had to chip in here, knowing something about how actors (which
> is basically what you're advocating) work in Scala. Some points:

Thank you. Your input is valued.

> - Message sends have to give you something that method calls don't

Right.

> Whether that's the ability to ignore not-understood messages (like in
> Obj-C)

That's one.

> , or making the message send-receive behavior asynchronous (like in
> Scala)

That's two.

> or ensuring messages are handled serially per-object,

This happens in either paradigm.

> I think this is a significant point: small things (lists, tuples,
> primitives) are kept as structs and the data inside them is manipulated
> directly,

Yes, and here is where something significant I think will happen.
Complicated data structures just simply don't get re-used. Python
allows lists within lists within lists, but any program that uses that
outside of n x n matrices won't ever get re-used ever. Because there
is no unified data model.

> and big things (web servers, background-workers, http clients) are
> then done with state-hiding and encapsulation and all that.

Yeah, that part is fine.

> Having a simple thing (like a list or a tuple) with encapsulation and
> sending messages to it is as silly [...]

Ah, but you see I'm envisioning a data ecosystem (to borrow a phrase)
for the Internet. A peer-2-peer model for sharing data. So sending
messages isn't so silly.

> In particular, your dislike for "lists within lists" seems incompatible with
> your desire for "more universal/general classes, building up to the
> complexity desired". Isn't that almost the perfect example of simple,
> general classes used to build up complex structures?

I think I see the source of confusion, I used the word "object" when
that is the term used in Python for lists, etc -- things used to store
data, but I see them as separate. I make a distinction between
classes which not only may be stateful, but be able to *do* things,
with data types which don't "do" things, but *are* things. It's a
subtle distinction, rather like languists distinguish between verbs
and object even though both are *words*.

Nick Coghlan

unread,
Mar 20, 2013, 8:47:27 AM3/20/13
to Mark Janssen, python-ideas
On Tue, Mar 19, 2013 at 9:36 PM, Mark Janssen <dreamin...@gmail.com> wrote:
> I think I see the source of confusion, I used the word "object" when
> that is the term used in Python for lists, etc -- things used to store
> data, but I see them as separate. I make a distinction between
> classes which not only may be stateful, but be able to *do* things,
> with data types which don't "do" things, but *are* things. It's a
> subtle distinction, rather like languists distinguish between verbs
> and object even though both are *words*.

Python, however, makes no such distinction - everything is either an
object, or a reference to an object. Hence, the puzzled
incomprehension in response to your proposal.

In Python, even numbers can do things, like tell you how many bits an
integer needs for its binary representation:

>>> 3000 .bit_length()
12

Message passing is generally seen in the Python community as a higher
level state isolation technique, something you use to manage
increasing complexity, not something you use all the time. It's
similar to the way we allow people to use Python for imperative or
functional code, even though it's all object-oriented under the hood.

Cheers,
Nick.

--
Nick Coghlan | ncog...@gmail.com | Brisbane, Australia

Stephen J. Turnbull

unread,
Mar 21, 2013, 9:37:42 AM3/21/13
to Mark Janssen, python-ideas
Mark Janssen writes:
> On Mon, Mar 18, 2013 at 7:14 PM, Haoyi Li <haoy...@gmail.com> wrote:

> > I think this is a significant point: small things (lists, tuples,
> > primitives) are kept as structs and the data inside them is
> > manipulated directly,
>
> Yes, and here is where something significant I think will happen.
> Complicated data structures just simply don't get re-used. Python
> allows lists within lists within lists, but any program that uses
> that outside of n x n matrices won't ever get re-used ever.

I don't see the distinction you're aiming at. PyPI, for example, is
full of extremely complicated data structures that get reused. Some
of them get reused fairly frequently, though not as often as simple
lists and tuples.

> Because there is no unified data model.

That I can agree with, as an absolute.<wink/>

> > Having a simple thing (like a list or a tuple) with encapsulation
> > and sending messages to it is as silly [...]
>
> Ah, but you see I'm envisioning a data ecosystem (to borrow a
> phrase) for the Internet. A peer-2-peer model for sharing data.
> So sending messages isn't so silly.

Sure. Smalltalk proved that. But it's also not a universal
improvement over the algebraic model of objects and operators, or
function and method calling, and so on. It can already be emulated in
Python (including the "ignoring messages you don't understand" aspect,
AFAIK) by using properties to turn what look like attribute references
into method calls (or with a rather uglier syntax, dict references).

I can see the advantage to you for your very specialized (at present,
anyway) research project of a fairly radical change to Python syntax,
but I don't see an advantage to the vast majority of Python users?

Haoyi Li

unread,
Mar 21, 2013, 2:08:31 PM3/21/13
to Stephen J. Turnbull, python-ideas
There are basically two discussions happening here: ADTs (small objects with public contents) vs Encapsulation, and method calls vs message sends. A few responses:

>> or ensuring messages are handled serially per-object,

>This happens in either paradigm.

I mean that messages sent from multiple threads are handled serially. If your entire program is single threaded (as many python programs are) or has a GIL which prevents multiple concurrent method calls, then i guess it isn't a big deal. But in a language that does have pre-emptive multithreading, this basically gives you a non-blocking, guaranteed (because there's no other way to interact with the object other than sending messages) "lock" around each object. Each object basically gets:

- its own single-threaded event loop to run its methods
- without the performance hit of creating lots and lots of threads
- without the overhead of running multiple processes and IPC betweeen the one-thread-per-process event loops (twisted, node.js, etc.) when you want to utilize multiple cores
- with minimal overhead over standard method calls (both syntactic and performance)
- for zero effort on the part of the programmer

These are definitely not things you get in either paradigm, and are probably the main reasons people use actors in Scala: they don't use them because they want a funky function call syntax, or they don't like static checking for unknown messages! It really does give you a lot of nice things in return for the funky "function call" (message send) syntax

>Yes, and here is where something significant I think will happen.
>Complicated data structures just simply don't get re-used.  Python
>allows lists within lists within lists, but any program that uses that
>outside of n x n matrices won't ever get re-used ever.  Because there

>is no unified data model.

I disagree completely. Coming from Java, where every list-within-list has its own special class to represent it, my experience is that is a terrible idea:

- Want to convert from one list-within-list to another list-within-list? Use a list comprehension and be done with it. Want to convert a special InsnList to a special ParameterList? Much more annoying.

- Want to do normal-list-things on your list-within-list? just use map() filter() reduce() or list comprehension. Want to do normal list things to you special InsnList object which isn't a normal list? Also much more annoying.

- Want to get something out of a list-within-list? just use square braces list_in_list[i][j]. Want to get something out of the special InsnList object? You'll need to look up the magic method to call (or message to send) to do it.

It's not like encapsulating the whole thing makes the data struture any less complicated: it just makes it more annoying to do things with, because now I have to learn your way of doing things rather than the standard python-list way of doing things.

In reality, nobody is ever going to re-use either your special InsnList object or my list-of-lists-of-instructions. However, when they're working with my list-of-lists, at least they can re-use other existing list-handling functions to manipulate it, and not have to dig through my docs to see what methods (or messages) my InsnList exposes.

In the end, message sends and method calls are basically isomorphic, so much so that in Scala you can transparently convert method calls to message sends under the hood if you prefer that syntax! Unless there's some significant advantage of doing it, it seems to me that the improvement would basically be forcing people to run a regex on their code to convert obj.method(a, b) to obj << (msg, a, b), and then life goes on exactly as it did before.

Mark Janssen

unread,
Mar 21, 2013, 6:22:46 PM3/21/13
to Haoyi Li, python-ideas
On Thu, Mar 21, 2013 at 11:08 AM, Haoyi Li <haoy...@gmail.com> wrote:
There are basically two discussions happening here: ADTs (small objects with public contents) vs Encapsulation, and method calls vs message sends. A few responses:

Thank you.  You've boiled the discussion down to the two main elements.  Abstract data type's (which I was calling "prototypes")  vs. Encapsulation is the important distinction.  It's not an easy distinction to see from the words alone.  The former, I'll say, is built from the ground (the bits) upwards, while the latter, while the latter from the top (the application-layer), downwards.  But, I wouldn't say that for ADTs that public contents were the important part.  In fact, I'd argue the opposite. 
 
>> or ensuring messages are handled serially per-object,

>This happens in either paradigm.

I mean that messages sent from multiple threads are handled serially.

Well this is where it gets bizarre to me.  Because, despite threading, the CPU still has to dispatch all processes and handle the data passing, ultimately.
 
If your entire program is single threaded (as many python programs are) or has a GIL which prevents multiple concurrent method calls, then i guess it isn't a big deal. But in a language that does have pre-emptive multithreading, this basically gives you a non-blocking, guaranteed (because there's no other way to interact with the object other than sending messages) "lock" around each object. Each object basically gets:

- its own single-threaded event loop to run its methods
- without the performance hit of creating lots and lots of threads
- without the overhead of running multiple processes and IPC betweeen the one-thread-per-process event loops (twisted, node.js, etc.) when you want to utilize multiple cores
- with minimal overhead over standard method calls (both syntactic and performance)
- for zero effort on the part of the programmer

Well, I argue that in the world of programming language evolution, all of these, except for the last, are premature optimizations.

>Yes, and here is where something significant I think will happen.
>Complicated data structures just simply don't get re-used.  Python
>allows lists within lists within lists, but any program that uses that
>outside of n x n matrices won't ever get re-used ever.  Because there
>is no unified data model.

I disagree completely. Coming from Java, where every list-within-list has its own special class to represent it, my experience is that is a terrible idea:
 
- Want to convert from one list-within-list to another list-within-list? Use a list comprehension and be done with it. Want to convert a special InsnList to a special ParameterList? Much more annoying.

How can you use a list comprehension unless you know the length or depth of each sub-list?
 
It's not like encapsulating the whole thing makes the data struture any less complicated: it just makes it more annoying to do things with, because now I have to learn your way of doing things rather than the standard python-list way of doing things.

Where that where the ClassName and the Class.__doc__ should get you half the way there.  There necessary component would be a universal/abstract data type.  I propose a FractalGraph which can handle and scale any level of complexity. As long as we have a universal data type, the class hierarchy that emerges will be simple and general to handle, rather than dealing with personal taxonomies.
 
In the end, message sends and method calls are basically isomorphic, so much so that in Scala you can transparently convert method calls to message sends under the hood if you prefer that syntax! Unless there's some significant advantage of doing it, it seems to me that the improvement would basically be forcing people to run a regex on their code to convert obj.method(a, b) to obj << (msg, a, b), and then life goes on exactly as it did before.

No.  While you're technically correct as to the issue of isomorphism.  In practice, the usage you propose does not help whatsoever.  "(mgs, a, b)" is too complex.  Firstly, in the message-passing scheme I'm proposing, you never pass in more than one piece of data, unless it's a very structured, perhaps (a single XML-like tree?).

mark

Haoyi Li

unread,
Mar 21, 2013, 7:49:44 PM3/21/13
to Mark Janssen, python-ideas
Well this is where it gets bizarre to me.  Because, despite threading, the CPU still has to dispatch all processes and handle the data passing, ultimately.

Yeah. It works automagically, though, really nicely. It means I don't need to mess around with a huge spaghetti of locks and mutexes and semaphores when i want to use multiple cores. Although the CPU has to handle all the processes and data passing, the programmer (almost) doesn't have to. That's a pretty big gain.

> Well, I argue that in the world of programming language evolution, all of these, except for the last, are premature optimizations.

I dunno, lots of people like event loops, not just the scala actors people: Go's goroutines, python's greenlets, ruby fibers, etc. are all doing this. They provide nice correctness (no pre-emption causing race conditions) and performance (OS threads are heavy!) characteristics. Looking at the "message passing" systems I know about:

- Erlang processes
- Go goroutines
- Scala actors
- Obj-C objects

3 out of 4 are basically using it for concurrency, for isolating mutable state and providing the multi-thread-serializable-calling behavior you called "bizarre". This is just to back up my claim that the things Scala-actors (and the other message passing systems above) give you w.r.t. concurrency is actually really nice, and even if you don't see the benefits, they're there and people love them.

How can you use a list comprehension unless you know the length or depth of each sub-list?

The most common cases are non-recursive data structures, so I already know their depth, the less common case is recursive data structures, and I recurse on them; people do it all the time. I mean you could encapsulate the recursion in a method which calls itself on its children, or you could ask for its children in your function and recurse on them yourself. Neither is really better or worse, just different approaches with different tradeoffs.

Where that where the ClassName and the Class.__doc__ should get you half the way there.  There necessary component would be a universal/abstract data type.  I propose a FractalGraph which can handle and scale any level of complexity. As long as we have a universal data type, the class hierarchy that emerges will be simple and general to handle, rather than dealing with personal taxonomies.

Isn't the idea of an "object" with "methods" and "fields" basically that universal data type? How is it yours will scale to any level of complexity and be simple and general to handle but the "object" universal data type doesn't?

> No.  While you're technically correct as to the issue of isomorphism.  In practice, the usage you propose does not help whatsoever.  "(mgs, a, b)" is too complex.  Firstly, in the message-passing scheme I'm proposing, you never pass in more than one piece of data, unless it's a very structured, perhaps (a single XML-like tree?). 

Is the proposal basically to use shorter methods with fewer parameters? I mean, a list of arguments (which could be objects and contain other objects inside) sounds exactly like an XML-like tree to me.


Here's an interesting question: Is there any existing language/system out there, that's built in the manner you describe (message passing etc.), which you can point at and say "see, they do it this way and it works much better"? That would help immensely in understanding what benefits you're envisioning, since I (and others?) apparently don't see them




Andrew Barnert

unread,
Mar 22, 2013, 5:08:19 AM3/22/13
to Haoyi Li, Stephen J. Turnbull, python-ideas
From: Haoyi Li <haoy...@gmail.com>

Sent: Thursday, March 21, 2013 11:08 AM


>I disagree completely. Coming from Java, where every list-within-list has its own special class to represent it, my experience is that is a terrible idea:


This is a side issue, but… that's not the problem with Java lists. After all, Haskell also has a separate type for every list-within-list, yet you can still use comprehensions, map/filter/reduce, etc., and they even work over abstractions rather than just lists (I promise, I won't use the m-word here). Even C++ has std::transform and friends. The terrible idea is having a rigid and non-extensible type system. Haskell (and, to a much lesser extent, C++) avoids that through explicit parameterization; Python (and, to a lesser extent, Smalltalk/ObjC/etc.) avoids it through implicit duck typing; Java forces the programmer to deal with it by writing horrible manual boilerplate.

>In the end, message sends and method calls are basically isomorphic, so much so that in Scala you can transparently convert method calls to message sends under the hood if you prefer that syntax! Unless there's some significant advantage of doing it, it seems to me that the improvement would basically be forcing people to run a regex on their code to convert obj.method(a, b) to obj << (msg, a, b), and then life goes on exactly as it did before.


Here is the main point. Everyone is reading their own ideas into the proposal, because nobody can believe it's as ridiculous as it sounds. The whole key to the proposal is that you _don't_ have messages with parameters like (msg, a, b); a message is just an object. You can do obj1 >> obj2, and that's all you ever need. obj2 knows what to do with obj1, so you don't need to tell it.

Since it's patently obvious that you _do_ need objects with more than one behavior, people assume he _must_ be talking about messages and objects in the sense of Smalltalk/Erlang/Scala/Go/etc.: a message as something that describes an action to take, with arguments. The fact that he's specifically referenced Alan Kay and Smalltalk and papers about this kind of message-sending makes that assumption even harder to avoid. But the assumption is wrong. You can't convert obj.method(a, b) to his syntax, because if you need to, obj isn't a good example of an object.


He's specifically said, multiple times, that if you think there are multiple things obj2 might want to do with obj1, that means you're not imagining the right kinds of objects. Lists, numbers, files, filesystems, servers, documents, hyperlinked webs of documents, GUI windows, database tables, events, animals, cars, ecosystems, user accounts—all of these things are bad examples of objects. And he hasn't given any good examples, no matter how many times he's been asked; the only examples he's given are lists, numbers, and filesystems, all of which he claims are terrible. While his objects are "universal", there are no such things that exist.

Except, of course, for single-argument, void-return functions. They work exactly like what he's describing as "objects". That observation has already been made three times, and he hasn't even responded. He just waits for someone else to come along, read something into his proposal that isn't there, and talk to them until they figure out he's a quack.

Reply all
Reply to author
Forward
0 new messages