|
The
Squeak Language stated informally
In
this section I will state and describe the Squeak Language, briefly SL, and do so in two ways, namely first
informally in English, and then formally though also in English, but now
using a few simple formal conventions for writing formal grammars that will
be first explained.
The formal
specification supplements the
informal exposition, and probably is in fact the easier to follow of the two,
for newcomers to Squeak.
The
present text is in part derived from the Greenberg-Black specification of the
Squeak Language and in part derived from a Backus-Naur specification of
Squeak 2.7 on the Squeak Wiki and the ANSI specification of Smalltalk.
A.
Informally
The
Squeak Language is designed to help people communicate with computers. Computers
are machines that can perform certain operations on given inputs that result
systematically in outputs. Computer languages tell a computer which operation
to perform, and have to be in a form which is valid input for the computing
machine while also being as easy to understand for humans as is possible.
The
Squeak Language, like any computer language, consists of certain sequences of
characters that can be produced by a computer keyboard, but of course not of
all any that may be thus produced. Hence a specification is needed for what
does and does not count as a term of the Squeak Language.
Common
and individual names in SL:
In the
Squeak Language there are names much like in other languages. They are called
Identifiers, and are
made up of sequences of letters or digits, without spaces or underscores:
Identifiers
An identifier in SL is a sequence of characters or digits that starts with
a letter.
- Smalltalk identifiers (and symbols) are
case-sensitive.
- It is a Smalltalk convention for identifiers
(instance and temporaries) of several words to begin with a lower case
character, and then capitalize subsequent words. (e.g.,
thisIsACompoundIdentifier).
- Certain identifiers, for example, globals
(e.g., Smalltalk) and class variables, are by convention initially
capitalized. The names of all classes are also global variables (e.g.,
SystemDictionary).
|
So any
keyboard output that conforms to this specification is an Identifier and
functions as a common or individual name of something, which can be assigned
to them by Squeak.
Terms
in SL:
To
this assigning we turn in a moment, but first we introduce a subset of the
Identifiers, namely the Literals or Constant Expressions. These have a value
assigned to them by Squeak, namely of the followin five basic kinds:
Characters
............. individual keyboard inputs
Numbers ............... series of characters that represent numbers
Symbols ................ series of characters that serve as constant names
Constant Arrays .. series of arbitrary items of fixed length
Strings .................. series of characters
Note
that the specification of Identifiers lays down what may be an Identifier of
Squeak, without being here more specific about specific Identifiers. To
these we turn now, starting with characters:
Literals (Constant
Expressions)
|
Characters (Instances
of class Character)
$x
"A character is any character (even unprintable ones), preceded by a
dollar sign"
$3 "Don't be shy about characters that are digits"
$< "or symbols"
$$ "or even the dollar sign"
|
So in
fact Squeak uses the $ character to indicate that the next item following it
is in fact a character in Squeak. (Here it should be realized that inside the
computer a character is a glyph - small drawing - associated with a unique
number. Hence in effect #hexadecimal means the hexadecimal is a character.)
Next
to characters, Squeak uses a fairly standard notation for Numbers, which come
in Squeak in quite a few kinds:
Numbers (Instances
of class Number)
In
the following, ==> means "prints as".
Decimal
integer.....................: 1234, 12345678901234567890
Octal integer or base 8...........: 8r177, 8r1777777777777777777777
Hex integer or base 16..........: 16rFF, 16r123456789ABCDEF012345
Arbitrary base integer say 2....: 2r1010 ==> 10
Integer with exponent...........: 123e2 ==> 12300, 2r1010e2 ==> 40
Float (double precision).........: 3.14e-10
Arbitrary base float................: 2r1.1 ==> 1.5
Float with exponent...............: 2r1.1e2 ==> 6.0
- Note that in any but the simplest first case
the base or exponent or precision are indicated (by r, e, .
respectively)
- Squeak supports SmallInteger arithmetic
(integers between -230 and 230-1) with fast
internal primitives.
- Squeak supports arbitrary precision
arithmetic seamlessly (automatically coercing SmallInteger to
LargePositiveInteger and LargeNegativeInteger where appropriate),
albeit at a slight cost in speed.
- Squeak supports several other kinds of
"numeric" value, such as Fractions (arbitrary precision
rational numbers) and Points. While there are no literals for these
objects, they are naturally expressed as operations on built-in
literals. ( "2/3" and "2@3",
respectively)
- Numbers may be represented in many radices,
but the radix specification itself is always expressed in base 10. The
base for the exponent part is the same as the radix. So:
2r1010 ==> 10, 10e2 ==> 1000 (=10 x 102), but
2r1010e2 ==> 40 (=10 x 22)
|
What's
noteworthy here about numbers in Squeak is that there are quite a few kinds
of numbers available in Squeak, including Fractions, and that the notation
for reckoning with numbers is somewhat different from what one would expect
if one is used to other languages, since Squeak reads its input from left to
right and has no operator-strength. So e.g. 2+3*4 is calculated by Squeak as
(2+3)*4 and not as (2+(3*4)), though introducing the brackets will in fact
force the latter.
Constant Arrays (Instances
of class Array)
#( 1
2 3 4 5 ) "An array of size 5 comprising five Integers (1 to 5)"
#( 'this' #is $a #'constant' array ) "An array of size 5 comprising a
String ('this'), a Symbol (#is), a Character ($a) and two Symbols
(#constant and #array)."
#( 1 2 ( 1 #(2) 3 ) 4 ) "An array of size 4 comprising two Integers (1
and 2), an Array of size 3, and another Integer (4)."
#( 1 + 2 ) "An array of size 3 comprising 1, #+, and 2. It is not the
singleton array comprising 3."
- Constant arrays are constants, and their
elements must therefore be constants. "Expressions" are not
evaluated, but are generally parsed as sequences of symbols as in the
example above.
- Constant arrays may contain constant arrays.
The hash sign for internal constant arrays is optional. (So #(1 #(2
3)) comes to the same as #(1 (2 3)) i.e. an array made up of the
constant 1 and the array made up of the constants 2 and 3 in that
order.)
- Identifiers and sequences of characters in
constant arrays are treated as symbols; the hash sign for internal
symbols is optional.
- Arrays are indexed with the first element at
index 1.
|
Arrays are the basic way for
a computer to store groups of things as units. In set-theoretical terms,
arrays are sequences or tuples of Squeak-constants, including other arrays. The
last statement. that Arrays
are indexed with the first element at index 1 comes to this: One may in
Squeak get the individual elements of the array by specifying their position
in the Array. This
will be explained later.
Symbols (Instances
of class Symbol)
#'A
string preceded by a hash sign is a Symbol'
#orAnyIdentifierPrefixedWithAHashSign
#orAnIdentifierEndingWithAColon:
#or:several:identifiers:each:ending:with:a:colon:
#- "A symbol can also be a hash followed by
'-' or any special character"
#+< "or a hash followed by any pair of special
characters"
- Symbol is a subclass of String (i.e. every
Symbol is a String)
- The primary difference between a Symbol and a
String is that all Symbols comprising the same sequence of Characters
are the same instance. Two different string instances can both have
the characters 'test one two three', but every symbol having the
characters #'test one two three' is the same instance. This
"unique instance" property means that Symbols can be
efficiently compared, because equality (=) is the same as identity
(==).
- "Identifier with colon" Symbols
(e.g., #a:keyword:selector:) are often referred to as keyword
selectors, for reasons that will be made clear later.
- "Single or dual symbol" Symbols
(e.g., #* or #++) are often referred to as binary selectors.
- The following are permissible special characters:
~!@%&*+=|?\<>/
- Note that #-- is not a symbol (or a binary
selector). On the other hand, #'--' is a symbol (but not a binary
selector).
|
Symbols are a systematic way
of creating unique names in
SL. The above specification gives some basic variants that are used in SL. The
specifications concerning = and == and the colons will be explained later. The
special characters are those that may occur in symbols next to digits and
capital and undercast letters. The reason #-- is not a symbol while #'--' is
a symbol is that -- is not an Identifier while '--' is a string and so when
preceded by # is a Symbol as per the first specification.
Note
that any computer language has something much like symbols, but there are
next to overlaps also variants in what different languages treat as
expressions that serve as unique names.
Strings (Instances
of class String)
'a
string comprises any sequence of characters, surrounded by single quotes'
'strings can include the "comment delimiting" character'
'and strings can include embedded single quote characters by doubling''
them'
'strings can contain embedded
newline characters'
'' "and don't forget the empty string"
- A string is very much like ("isomorphic
to") an array containing characters. Indexing a string answers
characters at the corresponding position, staring with 1.
|
So in
fact Squeak uses the ' character to indicate that any sequence of characters
inbetween two such characters is a String.
This may be initially confusing for many new to Squeak, since in Squeak the
conventions concerning ' and " are a bit different than in other
languages.
And
one must indeed be aware that strings may contain newline characters (that
don't display as character but mark the beginning of a new line in a string,
that's there for the human readers' convenience) and that the empty string is
a string as well.
Pseudo-Variables
|
Pseudo-variable
|
Description
|
|
nil
|
The
singleton instance of Class UndefinedObject
|
|
true
|
The
singleton instance of Class True
|
|
false
|
The
singleton instance of Class False
|
|
self
|
The
current object, that is, the receiver of the current message.
|
|
super
|
As
the receiver of a message, super refers to the same object as self. However,
when a message is sent to super, the search for a suitable method starts
in the superclass of the class whose method definition contains the word
super.
|
|
thisContext
|
The
active context, that is, the "currently executing"
MethodContext or BlockContext.
|
- Pseudo-variables are reserved identifiers that are similar to keywords in
other languages.
- nil, true and false are constants.
- self, super and thisContext vary dynamically
as code is executed.
- It is not possible to assign to any of these
pseudo-variables.
|
These
are special terms in SL used nearly everywhere. The given descriptions are
explained in part below, with Classes and BlockContexts.
Statements
in SL:
Sofar
no statements of Squeak have been specified. To this we turn now. First
there are Assignments that
assign values to identifiers:
One
important thing to notice is that ANY expression of SL can be assigned to a SL-identifier
and that an SL-identifier works like slot:
<Identifier, Expression>. There also is a default assignment namely nil. So in Squeak any
Identifier that has been declared has some value given by a Smalltalk
expression assigned to it, even if only nil.
Next,
the three symbols terms and := and _
(underscore) are dealt with by Squeak as assignment of an expression on the right to
an identifier on the left.
Then
every expression in Squeak has a value that Squeak can produce and calculate,
and what is in fact returned if one asks for the value of an identifier what
Squeak returns is the value of the expression assigned to the identifier.
Thus,
doing Alt-P on
3+4
produces 7
Finally, for this
reason
Comments
"a
comment comprises any sequence of characters, surrounded by double
quotes"
"comments can include the 'string delimiting' character"
"and comments can include embedded double quote characters by
""doubling"" them"
"comments can span many
many
lines"
|
The
option to write Comments applies
to Squeak code: Squeak will in fact skip anything between two ". A human
reader can read it, but Squeak skips it since it doesn't need it.
Now we
arrive at Messages, which are the the main Expressions in Smalltalk. They
come in three kinds, namely Unary, Binary and Keyword, and come with some
conventions:
Messages
Unary Messages
theta
sin
quantity sqrt
nameString size
1.5 tan rounded asString "same result as (((1.5 tan) rounded)
asString)"
- Unary messages are messages without
arguments.
- Unary messages are the most "tightly
parsed" messages, and are parsed left to right. Hence, the last
example answers the result of sending #asString to the result of
sending #rounded to the result of sending #tan to 1.5
|
On the
first three lines in the above examples the first term is an Identifier and
the second a Message, apparently intended to get the sinus, the square root
and the size (in some sense) of whatever is identified by the previous
term.
The
last example shows three Unary Messages to be executed in sequence, to the
following effect: Take the tan of 1.5, round the result off, and turn the
result of that (a number) into a string.
Here
we see two of the conventions at work: Smalltalk expressions are evaluated by
the interpreter from left to right, using values returned by the left as
arguments to the right.
In
fact the same applies to:
Binary Messages
3 +
4 " ==> 7 "
3 + 4 * 5 " ==> 35 (not 23) "
3 + 4 factorial " ==> 27 (not 5040) "
total - 1
total <= max "true if total is less than or equal to
max"
(4/3)*3 = 4 "==> true — equality is just a binary message, and
Fractions are exact"
(3/4) == (3/4) "==> false — two equal Fractions, but not the same
object"
- Binary messages have a receiver, the left
hand side, and a single argument, the right hand side. The first
expression above sends 3 the message comprising the selector #+ with
the argument 4.
- Binary messages are always
parsed left to right, without regard to precedence of numeric operators,
unless corrected with parentheses.
- Unary messages bind more tightly than binary
messages
|
Smalltalk
in fact deals with "3+4" as "take 3, and add 4 to that". The
same applies to "3+4*5", which accordingly has a different value as
the same expression has in standard algebra, in which * is supposed to bind
stronger than +, so that in ordinary algebra 3+4*5 = 3=(4*5)=23. Of course,
if this is what one wants, one can use parentheses in Squeak, for
"3+(4*5)" when evaluated by Squeak does result in 23 , as it
should.
Also
the main Binary Messages in Squeak and Smalltalk are those occurring in
standard mathematics, that concern the arithmetical functions, comparisons
and identities.
The
difference in Smalltalk between "=" and "==" concerns the
difference between identifiers and contents: "==" tests
whether two contents are the same (in some appropriate sense); "="
tests whether two identifiers are the same. The same contents can have
different identifiers, but the same identifiers cannot have different
contents.
|
Keyword Messages
12
between: 8 and: 15 " ==> true "
#($t $e $s $t) at: 3 " ==> $s "
array at: index put: value "==> answers value, after storing value
in array at index"
array at: index factorial put: value "same, but this time stores at index
factorial"
1 to: 3 do: aBlock "This sends #to:do: (with two parameters) to
integer 1"
(1 to: 3) do: aBlock "This sends #do: (with one parameter) to the
Interval given by evaluating '1 to: 3'"
- Keyword messages have 1 or more arguments
- Keyword messages are the least-tightly
binding messages. Binary and unary messages are resolved first unless
corrected with parentheses.
|
Most
messages in Smalltalk are Keyword Messages. Note that these in fact tell
whatever is identified by their first term to execute the method plus
parameters with values that follows in the keyword messages, for in fact
that's what a message is: An identifier followed by the name of a method with
parameters with proper values.
In the
first line, for example, "12" is send the message "between: 8
and: 15" in wich "between:" and "and:" are
parameters, identified by colons as last character, and 8 and 15 are the
values of these parameters. (This "between: " the reader can find
e.g. by a Method Browser in Smalltalk.)
Having
covered Messages, we turn to Expression Sequences - sequences of what we have
called statements of Smalltalk i.e. strings that the Interpreter passes as
well-formed and evaluates:
Expression Sequences
expressionSequence
::= expression (. expression)* (.)opt
box 20@30 corner: 60@90. box containsPoint: 40@50
- Expressions separated by periods
are executed in sequence.
- Value of the sequence is the value of
the final expression.
- The values of all of the other expressions
are ignored.
- A final period is optional.
|
Again,
an Expression Sequence can be assigned to an Identifier, which then can
be send the unary message value to get the result of evaluating the
Expression Sequence (which as remarked before happens basically from
left to right, by first evaluating unary messages, than binary messages and
finally keyword messages, and using the results of previous evaluations as
input to following evaluations).
Cascade
Expressions
receiver unaryMessage; + 23; at: 23 put: value; yourself
- messages in a cascade are separated by semicolons;
each message is sent to
receiver in sequence.
- Intermediate answers are ignored, but
side-effects on
receiver will be retained.
- The cascade answers the result of sending the
last message to
receiver (after sending all the preceding ones!)
|
This
differs from a sequence of Expressions separated by dots, since the dots
assure that the next expression is send to whatever is returned by the
previous expression. The term "side-effects" in fact tends to refer
to what one sees on the screen, such as a window being drawn, with result
"true" (which is ignored in a cascade).
Block
Expressions
Blocks,
actually instances of the class BlockContext. They are used all the time to
build control structures. Blocks are created using the [ ] syntax around a
sequence of expressions.
[ expressionSequence ]
"block without arguments"
[ (: identifier)+ | expressionSequence ]
"block with arguments"
[ (: identifier)+ | | identifier+ |
expressionSequence ] "block with
arguments and local variables"
[ 1. 2. 3 ] "a block which, when evaluated, will answer the value
3"
[ object doWithSideEffects. test] "a block which, when evaluated, will
send #doWithSideEffects to object, and answer the object test"
[ :param | param doSomething ] "a block which, when evaluated with a
parameter, will answer the result of sending #doSomething to the parameter.
- A block represents a deferred sequence of
actions.
- The value of a block expression is an object
that can execute the enclosed expressions at a later time, if
requested to do so. Thus
- [ 1. 2. 3 ] ==> [ ] in UndefinedObject>>DoIt
[ 1. 2. 3 ] value ==> 3
- Language experts will note that blocks are
rougly equivalent to lambda-expressions, anonymous functions, or
closures.
|
Block
are a very interesting and powerful features, basically for three reasons:
First, blocks are deferred instructions, waiting to be executed when
required; second, since any sequence of expressions can occur inside
them, anything computable can be made into such a deferred instruction; and
third the possibility of passing arguments makes the block very flexible.
Those
who are not enlightened by terms like "lambda-expressions" might
recall the notion of abstraction in set theory, as in "{x, y
: 0<=x+y<=1 }" = "the set of x,y such that the sum of x
and y is between 0 and 1 inclusive". Lambda-expressions a.k.a.
lambda-abstraction is a formalization of this kind of abstraction using
formulas and variables.
Incidentally,
at the time of writing - December 2001 - Blocks are not yet fully
implemented in Squeak, though there is hope this will happen within a few
months due to the efforts of some of Squeak's developers.
Evaluation Messages for BlockContext
|
Message
|
Description
|
Notes
|
|
value
|
Evaluate
the block represented by the receiver and answer the result.
|
1
|
|
value: arg
|
Evaluate
the block represented by the receiver, passing it the value of the
argument, arg.
|
2
|
|
valueWithArguments:
anArray
|
Evaluate
the block represented by the receiver. The argument is an Array whose
elements are the arguments for the block. Signal an error if the length
of the Array is not the same as the the number of arguments that the
block was expecting.
|
3
|
Notes
- The message
#value, sent to a block, causes the block to be executed and
answers the result. The block must require zero arguments.
- The message
#value: arg, causes the block to be executed. The block must require
exactly one argument; the corresponding parameter is initialized to arg.
- Squeak also recognizes
#value:value:, #value:value:value: and #value:value:value:value:. If you have a block with more than four parameters, you
must use #valueWithArguments:
|
This
belongs to Blocks as deferred instructions: Having a Block one can execute
the code it contains by sending value to it, plus eventual parameters.
Control
Structures
Alternative Control Structures (Receiver is Boolean)
|
Message
|
Description
|
Notes
|
|
ifTrue:
alternativeBlock
|
Answer
nil if the receiver is false. Signal an Error if the receiver is
nonBoolean. Otherwise, answer the result of evaluating
alternativeBlock
|
1,2
|
|
ifFalse:
alternativeBlock
|
Answer
nil if the receiver is true. Signal an Error if the receiver is
nonBoolean. Otherwise answer the result of evaluating the
argument, alternativeBlock.
|
1,2
|
|
ifTrue:
trueAlternativeBlock ifFalse: falseAlternativeBlock
|
Answer
the value of trueAlternativeBlock if the receiver is true. Answer the
value of falseAlternativeBlock if the receiver is false. Otherwise,
signal an Error.
|
1,2
|
|
ifFalse:
falseAlternativeBlock ifTrue: trueAlternativeBlock
|
Same
as ifTrue:ifFalse:.
|
1,2
|
Notes
- These are not technically control structures,
since they can be understood as keyword messages that are sent to
boolean objects. (See the definitions of these methods in classes True
and False, respectively).
- However, these expressions play the same role
as control structures in other languages.
|
If
control structures must be - sort of - hardcoded inside the language (like
Squeak's primitives, say) then the above kinds of ifs are
"technically" not control structures. Apart from that, they
are are, and are used all the time.
The
point of "Receiver is Boolean" is that what stands to the left of ifTrue etc. must evaluate as
true or false, which then may be picked up by ifTrue etc.
Alternative Control
Structures (Receiver is any Object)
|
Message
|
Description
|
Notes
|
|
ifNil:
nilBlock
|
Answer
the result of evaluating nilblock if the receiver is nil. Otherwise
answer the receiver.
|
|
|
ifNotNil:
ifNotNilBlock
|
Answer
the result of evaluating ifNotNilBlock if the receiver is not nil. Otherwise
answer nil.
|
|
|
ifNil:
nilBlock ifNotNil: ifNotNilBlock
|
Answer
the result of evaluating nilBlock if the receiver is nil. Otherwise
answer the result of evaluating ifNotNilBlock.
|
|
|
ifNotNil:
ifNotNilBlock ifNil: nilBlock
|
Same
as #ifNil:ifNotNil:
|
|
|
In
fact, these ifs are an interesting Smalltalk-feature, that arises out of
having the nil option, and that extend the possibilities of the
previous list of ifs, in that they can be send to anything, and not
just to a Boolean. Here the reader should remember that any variable is
initialized to nil by Squeak.
Iterative Control
Structures (receiver is aBlockContext)
|
Message
|
Description
|
Notes
|
|
whileTrue
|
Evaluate
the receiver. Continue to evaluate the receiver for so long as the result
is true.
|
|
|
whileTrue:
aBlock
|
Evaluate
the receiver. If true, evaluate aBlock and repeat.
|
|
|
whileFalse
|
Evaluate
the receiver. Continue to evaluate the receiver for so long as the result
is false.
|
|
|
whileFalse:
aBlock
|
Evaluate
the receiver. If false, evaluate aBlock and repeat.
|
|
|
This
corresponds to similar structures in other languages, though it must be
repeated again that control structures in Squeak and Smalltalk are
implemented in an original way (using the class Boolean: Check it out in a
System Browser in Squeak.)
Enumeration Control
Structures (Receiver is anInteger)
|
Message
|
Description
|
Notes
|
|
timesRepeat:
aBlock
|
Evaluate
the argument, aBlock, the number of times represented by the receiver.
|
|
|
to: stop do:
aBlock
|
Evaluate
aBlock with each element of the interval (self to: stop by: 1) as the
argument.
|
|
|
to:
stop by: step do: aBlock
|
Evaluate
aBlock with each element of the interval (self to: stop by: step) as the
argument.
|
|
|
This
also corresponds to similar structures in other languages. Here one also sees
how code is written in Squeak: The first example requires a number to its
left and the second is in fact an instance of the third. Note
that both "stop" and "step" are parameters.
Enumeration Control
Structures (Receiver is Collection)
|
Message
|
Description
|
Notes
|
|
do: aBlock
|
For
each element of the receiver, evaluate aBlock with that element as the
argument.
|
1
|
Note
- Squeak collections provide a very substantial
set of enumeration operators. See the section Enumerating
Collections on the Classes Reference.
|
This
is a most important control structure, that allows one to iterate a block
over the contents of tje receiver.
Case
Structures (Receiver is any Object)
|
Message
|
Description
|
Notes
|
|
caseOf:
aBlockAssociationCollection
|
Answer
the evaluated value of the first association in
aBlockAssociationCollection whose evaluated key equals the receiver. If
no match is found, signal an Error.
|
1
|
|
caseOf:
aBlockAssociationCollection otherwise: aBlock
|
Answer
the evaluated value of the first association in aBlockAssociationCollection
whose evaluated key equals the receiver. If no match is found, answer the
result of evaluating aBlock.
|
1
|
Note
- aBlockAssociationCollection is a collection
of Associations (key/value pairs).
Example: aSymbol caseOf: {[#a]->[1+1]. ['b'
asSymbol]->[2+2]. [#c]->[3+3]}
|
This
again corresponds to similar structures in other languages. The reason for
blocks to occur here is their power, and the reason for the associations is
that it enables one to immediately associate what the programmer want to be
associated to the cases found.
Expression
"Brace" Arrays
braceArray ::= { expressionSequence }
{ 1. 2. 3. 4. 5 } "An array of size 5 comprising five Integers (1 to
5)"
{ $a. #brace. array } "An array of size 3 comprising a Character ($a)
a Symbol (#brace), and the present value of the variable array."
{ 1 + 2 } "An array of size 1 comprising the single
integer 3."
- Brace arrays are bona-fide Smalltalk
expressions that are computed at runtime.
- The elements of a brace array are the answers
of its component expressions.
- They are a sometimes convenient and more
general alternative to the clunky expression "Array with: expr1
with: expr2 with: expr3"
- Indexing is 1-based: The first element
of a brace-array is at index 1.
|
As the
name indicates, braceArrays are a sort of array the contents of which are
evaluated by Squeak (and not just retrieved).
Answer Expressions
answerExpression ::= ^ expression
^
aTemporary
^ 2+3
- Inside the body of a method, an answer
expression is used to terminate the execution of the method and
deliver the expression as the method's answer.
- Answer expressions inside a nested block
expression will terminate the enclosing method.
|
An
alternative name is Return. Note the second point, and remember that a
return-expression inside a block need not be reached during execution of the
method.
Class Definition
Ordinary Class Definition
SuperClass subclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2' classVariableNames: 'ClassVarName1 ClassVarName2' poolDictionaries: '' category: 'Major-Minor'
Variable Class Definition
These forms of
class definition are used to create indexable objects, i.e., those like
Array, ByteArray and WordArray. They are included here for completeness,
but are not normally used directly; instead, use an ordinary object with an
instance variable whose value is an approriate Array (or other collection)
object.
SuperClass variableSubclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2' classVariableNames: 'ClassVarName1 ClassVarName2' poolDictionaries: '' category: 'Major-Minor' SuperClass variableByteSubclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2' classVariableNames: 'ClassVarName1 ClassVarName2' poolDictionaries: '' category: 'Major-Minor' SuperClass variableWordSubclass: #NameOfClass instanceVariableNames: 'instVarName1 instVarName2' classVariableNames: 'ClassVarName1 ClassVarName2' poolDictionaries: '' category: 'Major-Minor'
|
In fact, this is
the format the browsers propose and pop up when one starts writing a new
class, which one has to fill by specifying one's own terms after the colons.
The above is best understood by browsing the system and seeing how classes
are in fact written. (Incidentally, poolDictionaries seem to be hardly ever
used in Smalltalk, while "category" refers to one's organization of
one's classes in the browser: They are not used in programs.)
Method Definition
All methods
answer a value; there is an implicit ^ self at
the end of every method to make sure that this is the case.
Here is an
example (from class String).
lineCount "Answer the number of lines represented by the receiver, where every cr adds one line." | cr count | cr Character cr. count 1 min: self size. self do: [:c | c == cr ifTrue: [count count + 1]]. ^ count
|
The general point is that methods are meant to get values by
executing them, and the implicit ^self at the end of every method
assures that this will happen whenever it is executed.
Link to: The Squeak Language stated
semi-formally- that may be somewhat clearer, perhaps, and in any case
supplements the present exposition.
|