next up previous contents index
Next: 2.3 Sequencing Expressions Up: 2 Language Reference Previous: 2.1 Objects   Contents   Index

Subsections

2.2 Sending Messages

Expressions in Slate mainly consist of messages sent to argument objects. The left-most argument is not considered an implicit receiver as it is with most message-passing languages, however. This means that when identifying a variable, it is really a message that is being sent to the context or argument.

An important issue is that every message selector (and slot name) is case-sensitive in Slate, that is, there is a definite distinction between what AnObject, anobject, and ANOBJECT denote even in the same context. Furthermore, the current implementation is whitespace-sensitive as well, in the sense that whitespace must be used to separate messages in order for them to be considered separate. For example, ab+4 will be treated as one message, but ab + 4 is a send of a binary message.

There are three basic types of messages, with different syntaxes and associativities: unary, binary, and keyword messages. Precedence is determine entirely by the syntactic form of the expression, but it can of course be overridden by enclosing expressions in parentheses. An implicit left-most argument can be used with all of them. The default precedence for forms is as follows:

  1. Literal syntax: arrays, blocks, block headers, statement sequences.
  2. Unary messages.
  3. Binary messages.
  4. Keyword messages.
A concept that will be often used about message-sends is that of the name of a message, its SELECTOR. This is the Symbol used to refer to the message or the name of a method that matches it. Slate uses three styles of selectors, each with a unique but simple syntax.


2.2.1 Unary Messages

A UNARY MESSAGE does not specify any additional arguments. It is written as a name following a single argument; it has a post-fix form.

Some examples of unary message-sends to explicit arguments include:

Slate> 42 print. 
'42' 
Slate> 'Slate' clone. 
'Slate'
Unary sends associate from left to right. So the following prints the factorial of 5:

Slate> 5 factorial print. 
'120'
Which works the same as:

Slate> (5 factorial) print. 
'120'
Unary selectors can be most any alpha-numeric identifier, and are identical lexically to ordinary identifiers of slot names. This is no coincidence, since slots are accessed via a type of unary selector.

2.2.2 Binary Messages

A BINARY MESSAGE is named by a special non-alphanumeric symbol and 'sits between' its two arguments; it has an infix form. Binary messages are also evaluated from left to right; there is no special precedence difference between any two binary message-sends.1

These examples illustrate the precedence and syntax:

Slate> 3 + 4. 
7 
Slate> 3 + 4 * 5. 
35 
Slate> (3 + 4) * 5. 
35 
Slate> 3 + (4 * 5). 
23
Binary messages have lower precedence than unary messages. Without any grouping notation, the following expression's unary messages will be evaluated first and then passed as arguments to the binary message:

Slate> 7 factorial + 3 negated. 
5037 
Slate> (7 factorial) + (3 negated). 
5037 
Slate> (7 factorial + 3) negated. 
-5043
Binary selectors can consist of one or more of the following characters:

# $ % ^ * - + = ~ / \ ? < > , ;
However, these characters are reserved:

@ [ ] ( ) { } . : ! | ` &

2.2.3 Keyword Messages

A KEYWORD MESSAGE is an alternating sequence of keywords and expressions, generally being a continued infix form. Keywords are identifiers beginning with a letter and ending with a colon. Keyword messages start with the left-most argument along with the longest possible sequence of keyword-value pairs. The SELECTOR of the message is the joining-together of all the keywords into one Symbol, which is the name of the message. For example,

Slate> 5 min: 4 max: 7. 
7
is a keyword message-send named min:max: which has 3 arguments: 5, 4, and 7. However,

Slate> 5 min: (4 max: 7). 
5
is a different kind of expression. Two keyword message-sends are made, the first being max: sent to 4 and 7, and min: sent to 5 and the first result. Note however, that even though the first expression evaluates to the same value as:

Slate> (5 min: 4) max: 7. 
7
that this is still a distinct expression from the first one, with two message-sends of one keyword each instead of one send with two keywords. Actually, this expresses the definition of min:max:, although this is perhaps one of the most trivial uses of method names with multiple keywords.

Keywords have the lowest precedence of message-sends, so arguments may be the results of unary or binary sends without explicit grouping required. For example, the first expression here is equivalent to the latter implicitly:

Slate> 5 + 4 min: 7 factorial max: 8. 
9 
Slate> (5 + 4) min: (7 factorial) max: 8. 
9

2.2.4 Implicit-context Messages

Within methods, blocks, and even at the top-level, some expressions may take the surrounding context as the first argument. There is an order for the determination of which object becomes the first argument, which is entirely based on lexical scoping. So, within a block, an implicit send will take the block's run-time context as argument. The next outer contexts follow in sequence, up to the top-level and what it inherits from, which generally turns out to be the global object that roots the current session.

Specifically, any non-literal expression following a statement-separator or starting an expression within parentheses or other grouping is an implicit-context send.

There are some very common uses of implicit-context sends. In particular, accessing and modifying local variables of a block or method is accomplished entirely this way, as well as returns. For example,

[| :i j k | 
 j: i factorial. 
 k: (j raisedTo: 4). 
 j < k ifTrue: [| m | 
   j: j - i. m: j. ^ (m raisedTo: 3)]. 
 k: k - 4. 
 k 
].
is a block which, when invoked, takes one argument and has another two to manipulate. Notice that the local slot j is available within the enclosed block that also has a further slot m. Local blocks may also override the slots of their outer contexts with their input and local slots. In this case, the identifiers j and j:, for example, are automatically-generated accessing and update methods on the context. Because j: is a keyword message, if the assigned value is a keyword message-send result, it must be enclosed in parentheses to distinguish the keyword pattern. The ^ (m raisedTo: 3) message causes the context to exit prematurely, returning as its value the result of the right-hand argument. All methods have this method defined on them, and it will return out to the nearest named block or to the top-level.

In some cases, it may be necessary to manipulate the context in particular ways. In that case, it can be directly addressed with a loopback slot named thisContext, which refers to the current activation. The essence of this concept is that within a block, x: 4. is equivalent to thisContext x: 4.2


next up previous contents index
Next: 2.3 Sequencing Expressions Up: 2 Language Reference Previous: 2.1 Objects   Contents   Index
Brian Rice 2005-11-21