Everything in Smalltalk is an object, and all computation is performed by sending
messages to objects. Each object is an instance of a class. All instances of a class share the same methods and structure. Every class is a subclass of either another class or "nil" (a special object denoting "no value"). Each class "inherits" the methods and structure of its superclass. So, the key piece of Smalltalk syntax is the message.
There are three forms to the message send. Unary messages are named with a plain word, such as "beep" in (anyObject beep). Binary messages are made of one or two symbols, such as "+" in (17 + 5) or ">=" in (2 >= someVar). Keyword messages can take any number of arguments, with one colon (":") in the name for each argument. For example, the message at:put: takes two arguments, as in (myArray at: 3 put: 'third').
The expression (Rectangle new x: 13 y: 0) has two messages. The first is #new, which is a
unary message. The second is x:y:, which is a keyword message with two arguments. Note that
x: and y: are not separate messages; it is a single message with two arguments. If x: and
y: were separate messages then we'd have to write something like ((Rectangle new x: 13) y: 0)
to keep them separate.
The first line of a method defines the name of the method and the name of its arguments.
^self < aNumber ifTrue: [aNumber] ifFalse: [self]
This is the max: method, which has one argument. The method sends the binary message < and also
the keyword message ifTrue:ifFalse:
It also has a return statement, which is what the ^ means.
It also has blocks, which are represented by square brackets.
There are a variety of "literals" in Smalltalk. Literals are written "literally" into the source.
7, 'hello', and 14.6 are all literals. #hello is also a literal, a symbol. It is like a string,
except that all symbols with the same value are in fact the same object; that is, every #hello symbol is the
exact same object as every other #hello symbol. #(1 2 17) is a literal
array with three elements. The character "c" is represented by $c. Some implementations include other types of literal.
A programmer will define methods for a class. A method consists of the header that defines its name and
arguments, followed by a series of expressions. You've seen most of the components of an
expression already: message sends, variable references, literals, returns, and blocks. In addition,
you can assign to variables and have a sequence of statements.
x := x + 1
is an assignment statement that increments the variable x. Note that +
is just a message (a binary message) sent to x, with 1 as an argument. But the assignment operator is not a message. It may be written as either the combination colon-equals, or as a left-pointing arrow (generated by typing an underscore).
total := 0.
numbers do: [:each | total := total + each]
is a sequence of two statements. The first sets a variable to 0, and the
second adds all the numbers in the collection numbers
to it. do:
is a message
that is sent to numbers
to iterate over them. It takes a block (surrounded by square brackets) as an argument.
This block itself has an argument, each
. Note that block arguments are declared by
preceding them by a colon. The | separates the arguments of the block from the
body of the block.
So, now you know all the syntax in Smalltalk! And it is on one page.
Of course, the complexity of Smalltalk is in the class library, not the syntax.
You can learn the rules of the syntax in an hour, and after a week or two of
practice, they will seem obvious. But the class library will take years to master.
How does smalltalk know + is just a binary operator?
It's not an operator, it's a message - and it gets looked up the same way any other message does. The only special thing about binary messages is this: They consist of 1 or 2 characters only, they always take one argument, and they can only be made from a limited set of characters.
provides a sketch of the grammar in his comparative languages class (http://www.cl.cam.ac.uk/Teaching/1998/CompPrLs/slides9.ps
) to indicate how simple the language is (needs work, though):
BODY -> | name ... name | E . E ... E
E -> name x Transcript := ....typo in Richards' notes
| # E #green
| number 123
| string 'hello'
| ( E )
| ^ E return with value of E
| [ E . E ... E ] [Transcript show: .hello.]
| [ :name ... :name | E . E ... E ] [: x | x + 1]
| E name
| E name E ... name E
| E name E ... name E ; ... ; name E ...