I'm not Alan Kay, nor do I pretend to think like him, but having done some experiments on what I think he was suggesting I think the distinction between message passing with a method call is a bit of a red herring. Message passing can obviously be implemented with function calls. When he's talking about "messages" he's not referring to implementation. He's referring to constraining where data can be accessed when doing a computation.

Because a lot of people (including me) have a Simula based view of "object oriented", we tend to think of objects as data structures with functions attached to them. Alan Kay had a different view, as far as I can tell. He viewed objects as being a collection of abilities. You could invoke these abilities by sending the object a "message". How you send that message is irrelevant. The important thing is that the object is not a collection of data, but rather the object contains the program state necessary to provide the ability (and nothing more). One of the things he talks about (I can't remember if he does in this specific email exchange, though) is the idea that once the data is inside the object, you can't actually access it any more. It becomes a detail that the programmer doesn't have to worry about.

As an example, it's tempting to look at a point on a 2D plane as a tuple containing an X coordinate and a Y coordinate. However, let's forget about the data and instead think about the actions that you might want to do with a point. You might want to construct a vector from it (normalised from the point 0,0). You might want to translate it (by giving it a vector). You might want to rotate it around another point at a certain angle, etc, etc. From the outside perspective there is no reason to access the X and Y coordinates. We don't have to care about what a point object contains -- we only have to care about what messages it responds to.

But how is that really different that having a struct with X and Y and a bunch of functions attached to it? I thought pretty hard about this and one of the things I thought about was what if we approached this in a more functional, rather than imperative fashion. Alan Kay was, after all, coming from an FP background.

For example, let's say that we have a collections of points and we want to "indent" them by pushing them all to the right based on the X coordinate of an existing point. Our "normal" approach would be to get the X coordinate of the existing point and then add that value to the X coordinate of all the other points.

Instead, though, what if we had a method on Point that accepted a function. The method would call the function and furnish the x coordinate (we could call it "with_x", perhaps). Now we can use that method to construct a Vector, setting the x coordinate of the vector to the x coordinate of the point. We could then map over our collection of points and translate using the vector.

The difference is subtle, but I think it's important. With a struct, we essentially export program state out of the Point object. With this more functional approach, we run the function within the Point itself. In other words, we are asking the Point to construct the Vector itself, by sending it a message.

I think this is what Alan Kay meant when he talks about message passing. It's not about the mechanism of the passing of messages, it's about where the computation is performed as a result of that message passing. In our example, the X coordinate of the point never "leaks out" of the point. We can use it in the context of the point, but we can just grab it in the middle of some other computation.

Is that distinction important? I've tried to write some non-trivial code in that style and I really liked how it came out. I'm not sure if it's "better" than doing it another way, though. I would have to spend considerably more time with that style of programming to say for sure.