Message Passing

What is message passing?

There are two definitions in widespread use, which refer to two completely different things.

The definition from Smalltalk Language: A message is simply a method call on an object. Smalltalk messages are perfectly synchronous (the caller waits for the callee to return a value), and not terribly different then function/method calls in other languages. A few key points about Smalltalk message passing:

Like C/C++/Java/ML/Lisp/Scheme, and unlike Haskell, Smalltalk messages are strict--all arguments are evaluated before the message is sent.

However, Smalltalk blocks make it very easy to implement Lazy Evaluation or Normal Order Evaluation semantics (see Smalltalk Blocks Are Thunks In Disguise). Simply pass a block as an argument, and the contents of the block won't be evaluated until someone passes the block the "value" message (or value: or value: value:, etc.) Scheme Language has a similar mechansim with delay and force. (See Explicit Lazy Evaluation)

Like C++ and Java (and unlike Common Lisp Object System, Dylan Language, etc.), Smalltalk messages are Single Dispatch. The types of the arguments have no say in what method is selected to receive the message), though Smalltalk makes delegation easy.

The syntax of Smalltalk message invocations is somewhat unusual, though highly readable once you get used to it.

The definition from many concurrent programming paradigms: A message is a method for asynchronous dispatch, and used to communicate between different processes (which may run on different machines). Different concurrent models have different semantics regarding messages, such as whether or not the receiver and sender must rendezvous, whether or not the receiver must name the sender, etc. See Message Passing Concurrency and Process Calculi for more information.


The Message Passing story arises entirely out of a tragic confusion engendered by Alan Kay's research group. The initial variants of the Smalltalk Language family of languages were strongly inspired by Alan Kay's knowledge of Carl Hewitt's research on the Actor System model of computation.

No. Carl Hewitt's Actor System model did be strongly influenced by Alan Kay's Smalltalk-72 implementation that already had existed. see ref. acknowledgements by Carl Hewitt in www.cypherpunks.to wayback pdf

Actor System research was based on the assumption that massively parallel, distributed, computer systems could become prevalent, and therefore a convenient and efficient way to structure a computation was as a large number of self contained processes, called actors, communicating by sending messages to each other.

Alan Kay had also been exposed to the Object Oriented ideas in SIMULA-67, which were about a program decomposition paradigm, a way to structure programs, not computations. It was however easy to see that in general Actor System computations are naturally Object Oriented too, even if most Object Oriented languages are based on the procedural model of computation, and a few even on the logic model of computation.

Therefore the first few languages in the Smalltalk Language family were not procedural, and did not have procedure calls, but variants of message sending in the Actor System sense. In particular this applied to Smalltalk-76, which is the language described in the first famous article about the Smalltalk family of languages in Scientific American.

With Smalltalk-80 any trace of Actor System orientation were removed, in part because Actor System computations are very expensive to simulate on conventional workstations, in part because Alan Kay's group were influenced by the Lisp research being performed on the same workstations at Xerox Parc.

Unfortunately even if Smalltalk-80 is a thoroughly conventional procedural language (and a fairly close variant of Lisp, even if with different syntax and details) Alan Kay and his group and the Smalltalk-80 community continued to use Actor System terminology, retaining the message passing nomenclature for what had become conventional procedure calls (there is a single, hard to spot, note in one of the Smalltalk-80 book where it is stated clearly that message passing in that language really means the same as procedure calls).

This unfortunate terminological issue has created endless confusion as to a large extent the mythical relevance of Smalltalk-80 and the conflation of Actor System terminology with procedural semantics and Object Oriented concepts have muddle considerably the difference between these very different categories.

Many years after Smalltalk-80 was released Alan Kay seems to have come to regret the switch to procedural languages, arguing that the performance driven switch to a procedural computational model had been a mistake as increases in hardware performance would have made the simulation of Actor System based computations on procedural hardware feasible, and that the Actor System model of computation is preferable in his view to the procedural one.

However he has also stated that one of the most important recent books is The art of the metaobject protocol which is entirely about advanced techniques related to procedural OO languages, which raises the possibility that he himself suffers from some confusion.


Most C programmers seem to be moving to Object Oriented Programming in the Cee Language: They define structs and have functions for creating and destroying the structs. They implement some form of reference counting for garbage collection. However, they never seem to implement message passing. Is message passing an important part of object oriented programming or is it really not necessary?

Do you mean the Smalltalk definition, or the concurrent-programming definition?


Message passing is really unrelated to Object Oriented Programming, although usually a "message" is created as an object.

I use the term "message passing" to mean "queuing of communication between a source (sender) and a destination (receiver)", without regard to technology used (usually asynchronous is implied however). JMS is one technology to do this, but I've also used a simple event queue/dispatcher to do message passing within a single Java Virtual Machine. Other examples of tools are given in the Message Bus topic. The Multi Caster pattern is the way to go if things are complex enough to need many processes. -- Stanley Knutson

A great definition

Jerry Smith on www.jguru.com posted a nice summary:

Message passing is a general term for a variety of strategies for high-level, structured interclient communication. For example, a mobile agent framework could provide classes and methods with which two agents (on two different computers) send each other messages. The steps required to send and receive messages are specific to the framework. JMS supports two common message passing strategies, namely, point-to-point and publish/subscribe. JMS can be utilized by any (Java-based) distributed software components; of course, the JMS middleware must be available.

--

Most C programmers seem to be moving to Object Oriented Programming ... However, they never seem to implement message passing.

As a Cee Language programmer, I don't quite understand the point. "message passing" seems to mean two very different things.

In a object-oriented context, as far as I can tell, "message passing" is a fancy way of saying "function call". Say someone writes animal.talk("Hello!") or anAnimal talk:'Hello!' and says "I'm sending this animal the 'talk' message". But the computer acts just the same as if a Cee Language programmer writes "talk(animal,"Hello");" and says "I'm calling the talk() function with this 'animal' structure.". Not even close, the C implementation doesn't change its behavior based on the type of "animal".

No, that's merely a commonly appropriate optimization of a more general mechanism. Activation records in Smalltalk and in Scheme need not follow a strict LIFO ordering, even though that is the most common in any language, and is why they are usually optimized as simple LIFO stack-based function calls. There was some strong communication between Parc and MIT in the 1970s that lead up to all this, but anyway, once you're doing non-LIFO function calls, you start getting things that instead could be viewed as messages between threads.

Is this Cee Language programmer implementing message passing ? If not, what do you mean by "message passing" ?

In a networking application, "message passing" means "sending a message over the wire from a program on this computer to a program on that computer". For example, in X windows, sending a message from an application running on one of the campus Sun boxes "draw a white rectangle" to the Linux box on my desk at home. There's usually a buffer at both ends that can hold several messages. Occasionally the 2 programs run on the *same* computer -- then the OS simulates a "virtual wire" by directly copying from the out buffer into the in buffer.

I think of them as completely different things, because: What happens when a program is in the middle of handling one message, and then a second message come in ? In the OO case (a recursive call), the machine puts the first message on hold, takes care of the second message, then returns to processing the first message. In the networking case, the machine leaves the second message in the buffer until it's good and ready for it.

Common, but certainly not necessarily true. Input queues can be priority ordered, for instance.


I am implementing the "non-function call" kind of message passing between Objects in my language that are virtually all running independently of all others (green threads). Data is passed by a MAP that I call a "bag of variables" to "interface" functions on the Object that can accept only "MAP messages". My messages can be synchronous or asynchronous and they can be passed on (forwarded) to other Objects easily. All messages are queued and once an Object receives a message, any new messages have to wait until the current message has completed. One last thing, an Object can send and wait for messages that bypass the input message queue if it wants to.

The advantage of using a MAP (set of any group of variables or collections) is that input to interfaces can be drastically changed without invalidating (or re-compiling) other calls, as the MAP can contain any group of objects, unlike an object. Functions have a set number of parameters, in a specific order, with specific types. Maps on the other hand can contain any group of variables in no specific order, of any type. Maps aren't as efficient as functions but are significantly more flexible. In my system, messages are used at the higher level and functions are used at the local level.


See original on c2.com