One True Message Send
Grace is a pure object-oriented language. Everything in the language is an object, and all computation proceeds by sending (dynamically dispatched) messages to objects. In this, Grace follows most strongly in the Smalltalk tradition. Like Smalltalk, Grace has “One True Message Send” rule that explains how expressions are evaluated: a message that is sent to a receiving object is looked up in the receiving object’s definition, and if a matching method is found, that method is executed. (What happens when a message is not found will be the subject of another note). This “One True Message Send Rule” is followed for all types of Grace objects, whether the builtin Strings, Booleans, and Numbers, or objects defined in libraries or by user code.
Message-send is the principal operation in Grace; as far as possible, other operations in the language (especially control structures) are phrased as message-sends. This is important because, if classes introduced by libraries are going to be “first class”, it must be possible for them to define their own control structures, and have those control structures be the social equals of the built-in control structures. In effect, we can extend the syntax of Grace in the libraries.
The syntax of message-send is more like Java or C# than Smalltalk: a receiver (sometimes implicit), then a message name (an identifier), then any arguments in parenthesis. As in Smalltalk, however, it is possible to break up a long argument list and distribute it throughout the message name, so one can define both of the following
1 2 |
drawLineFrom(source)To(destination) movePenTo(x,y) |
It is up to the designer of an interface to decide on the best syntax for the language of messages that she is creating. One the interface designer has made her decision, clients have to follow along; it’s important that two sends of the same message look alike.
Arguments are always passed by object reference, and no implicit conversions or copying ever takes place.
Grace uses the keyword self to refer to the current object – what Simula, C++, and Java refer to as this. As in Java, Eiffel, and Self, the receiver of a message can be left implicit if it is self. Why self rather than this? Because it’s impossible to lecture about a language without using the English pronoun “this” in its ordinary sense!
Messages that take no arguments don’t get any parenthesis. This is because Grace has one shared namespace for method names and variables in objects. Thus, count could be either an access to a local variable or a send of the message count to self; to decide which one need only look at the declaration of count.This is a deliberate choice: the syntax abstracts away the implementation detail of whether a particular attribute is implemented by a variable or a method, and changing from one to the other does not require code that accesses the attribute to be modified. This is in contrast to C++ and Java, which use separate namespaces for variables and methods, and separate syntax for variable access and message send.
The motivation for allowing the arguments to be distributed through the name of a message is primarily to allow libraries to implement readable control structures. So
1 |
while {f.hasNext} do { bag.add(f.next) } |
which looks like a conventional while loop, is actually a send of the message while()do() to self. To promote this usage, we allow the parameter parenthesis to be omitted if they would be adjacent to the pair of braces that create a closure. Moreover, because of Grace’s layout syntax, the above example can also be written as
1 2 3 4 |
while f.hasNext do bag.add(f.next) |
where the braces are themselves replaced by layout.
This will allow libraries to implement constructs for things like atomicity, finalization and locking using messages. For example:
1 2 3 4 5 6 7 8 9 10 11 |
atomic t := x; x := y; y := t do something complicated that may fail finally notify("Job Completed") whileHolding (anAppropriate.lock) do let transferees = sourceObject.removeAll destinationObject.addAll(transferees) |
Grace’s One True Message Send rule has a number of consequences. One of the most important is that Grace does not allow overloading on argument type as in C++ or Java and their descents (C#, Scala): static type information never affects the execution of correct programs in Grace. So, if you want two methods on the same object to behave differently, you will have to give them distinct names. We expect sales of Roget’s Thesaurus to rocket.
At present we are not sure whether to support variadic methods. Most languages that started without variadic methods have added them; not having them may force the programer to create a tuple.
We currently propose that a single argument does not need to be enclosed in parentheses.