In C++ and Java and many other OOP languages, in order to send a message to an object, you have to use the
object.function() syntax […]
First, an important correction: they use the syntax
object.function(). Messages and functions are fundamentally different.
But why was this syntax chosen to send a message? why for example wasn't the
function(object) syntax chosen instead?
I want to challenge the premise of your question because there are object-oriented programming languages that use or at least alternatively allow this syntax.
For example in Lark
is simply syntactic sugar for
Also, interestingly in Python, methods are defined as functions taking the receiver as an argument:
def bar(baz, qux):
# within the method body, `baz` is the receiver
but they are called with the receiver as a special argument using the dot-message-sending syntax:
foo = Foo()
# within the method body, `baz` is now `foo`.
Conventionally, this first parameter is named
self, but that is only a convention.
This is the syntax used by Simula (1962), considered to be the first object-oriented programming language. Unfortunately, both designers of Simula, Kristen Nygaard and Ole-Johan Dahl, died in 2002, so we can't ask them why they chose it. However, you might find that they have documented their rationale in one of their papers.
However, there is a very good reason to distinguish the "special" zeroth argument from the other arguments, and that reason is that the "special" argument is … well special.
A method has privileged access to the internal representation and the private API of the receiver. Therefore, the receiver is different, and it makes sense to distinguish it from the rest of the arguments. If you have
message(object, arg1, arg2)
then there is no indication that
object is treated different from
arg2. But they are different: the method can access the internal representation and the private API of
object but only the public API of
arg2. Whereas with
you can clearly see that
object is different from
Additionally, Simula was designed to be a fairly faithful superset of ALGOL and
function(object) already has a meaning in ALGOL (subroutine call) that is different from message send, so that might also have been a reason not to overload it with two different meanings. It gets especially confusing when you have a subroutine named
foo in scope and
object also has a
foo method, then what does
and are all OOP languages use the
object.function() syntax to send a message?
No, of course not. There are thousands of languages, it would be a miracle if they all used the same syntax.
Smalltalk, Self, Newspeak, Objective-C, Objective-C++, Objective Modula-2, Fancy, Finch, Nu
The other extremely influential OO language next to Simula, Smalltalk, uses the so-called "Smalltalk keyword selector syntax". The message sending operator is simply the space, and the message is a "keyword selector" with the arguments written between the keywords. A "sentence" is ended with a period.
anArray ← Array new.
anArray append: 23.
anArray append: 42.
anArray at: 2 put: 4711.
"anArray will now contain the elements (23 4711)."
"If you want to send multiple messages to the same receiver, you can use a cascade:"
at: 2 put: 4711.
Note: The name of the method in the last line is
This syntax is also used by many of Smalltalk's descendants, successors, and derivatives, including Self (one of the influences on ECMAScript) and Newspeak as well as Fancy, Finch, Nu, and countless others. The most well-known language that inherited it from Smalltalk is Objective-C, which was until recently the primary language for macOS, iOS, iPadOS, tvOS, and watchOS development, and still plays an important role there.
Objective-C++ is interesting. Objective-C was created by taking the Smalltalk object model and Smalltalk message sending syntax and adding it to C as an orthogonal language extension. ("Extension" meaning that every legal C program is also a legal Objective-C program with identical semantics, and "orthogonal" meaning that the C part and the Objective part mostly don't interact.) Because Objective-C was designed as an orthogonal extension, it was actually possible to take the "Objective" part and apply it to other languages. (For example, Objective Modula-2.)
So, what do you get when you orthogonally extend C++ with "Objective"? You get a language with two separate object models and two different message sending syntaxes!
Carl Hewitt's PLASMA uses
message ⇒ object
object ⇐ message
interchangeably, depending on which one reads better in a certain context.
Note that in PLASMA, the message is not just a "message name" as it is in Simula or Smalltalk, but an object itself. For example, to add some numbers together, you would send the message
[1 2 3 4] (an array of numbers) to the object
+ like this:
[1 2 3 4] ⇒ +
+ ⇐ [1 2 3 4]
On the receiver side, you define a receiver pattern, which uses a triple-shafted arrow:
Io, Ioke, Seph, Atomo, Scala
In Io, Ioke, Seph and other languages based on similar ideas (e.g. Atomo), whitespace is used as the message sending operator as in Smalltalk, but arguments are passed in a parenthesized argument list like in ALGOL-style subroutine calls:
object message(arg1, arg2)
If there is only one argument, it is allowed to omit the parentheses, so you are allowed to write
2 + 3
instead of having to write
object.message() by default, but it allows to leave out the
., and if there is only a single argument, it also allows to leave out the parentheses.
Lisps (e.g. Clojure, Hy)
Lisps that support object-orientation typically keep the Lisp-style syntax. In Clojure and Hy, a method call looks like this:
(.message object arg1 arg2)
Grace uses a mixture of Simula-style and Smalltalk-style:
"abcdefghi".substringFrom 3 to 6
sends the message
substringFrom(_)to(_) passing arguments
Ruby, CoffeeScript, CokeScript, Coco
Ruby, CoffeeScript, Coco, and many others use Simula-style but allow to leave out the parentheses:
object.message arg1, arg2
Lua does not have OOP as part of its language semantics, but it does have some syntactic features that make it possible to implement OOP as a library while still looking like it is part of the language. This is quite interesting because it makes it possible to have multiple competing object systems in the same language, and choose the best one for the job.
object.message(object, arg1, arg2)
but it guarantees that
object will only be evaluated once.
Whether or not you consider Erlang object-oriented is a matter of opinion, but it definitely supports message sending:
object ! message
"Interesting" syntax sugar
Scala has right-associative operators. Any operator that ends with a colon
: is right-associative and has the argument on the left and the receiver on the right:
a + b
// is syntactic sugar for
a +: b
// is syntactic sugar for
Languages in which everything is a message send
In some languages, really absolutely everything is a message send. For example, in Ioke, Seph, and Monte, list or array literals are message sends, even number literals can be.
For example, in Ioke
[1, 2, 3]
is actually the message send
(1, 2, 3)
is actually the message send
"""42""" is not actually legal Ioke syntax. These methods take a so-called "strange object" as an argument, which is an object that belongs to the underlying platform and cannot be represented in Ioke. I am using this syntax here to mean "the strange object representing
is actually the message send
so, this is sending the message
internal:createText to what Ioke calls the "current ground", and the argument is a so-called "strange object" which is an object that is not actually an Ioke object but an object of the host platform. (We have to start the bootstrapping process somewhere.) So, in the JVM implementation of Ioke, this would be a
java.lang.String and in the CLI implementation, it would be a
By overloading these methods, I can overload the meaning of literals. This is used in Ioke's parser generator library, where
"a" for example does not mean "the string containing the character
a" but "a parser that recognizes the character
Of course, until now, we have only looked at single-dispatch classical and prototype-based OO. There is a whole slew of other approaches such as multiple-dispatch OO that by necessity have different syntax.