Welcome to the Squeak pages of Maarten Maartensz. See:  Map + Tour + Tips + Notes + News + Home



Squeak-subjects

 

 

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. 

 

Squeak Smalltalk Syntax: the Basics

     Common and individual names in SL: 

  • Identifiers: Terms for arbitrary common and individual names that may be assigned values in SL.

    Terms in SL:

  Literals: Terms for constants in SL.
      Characters
      Numbers 
      Constant Arrays
      Symbols
      Strings

  Pseudo-variables : Special terms for constants in SL.

Statements in SL:

  Assignments : Statements assigning values to Identifiers

  Messages : Statements that tell the computer to calculate something

  Expression Sequences

  Comments :

  Cascades

  Expression Blocks

  Brace Arrays

If-then-else in SL:

  Control Structures

Classes and Methods in SL:

  Class Definition

  Method Definition

 


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:

Assignments

identifier   expression
identifier :=  expression    " := is always a legal alternative to
, but the pretty printer uses "

foo 100 factorial
foo bar 1000 factorial

  • The identifier (whether instance variable, class variable, temporary variable, or otherwise) will thereafter refer to the object answered by the expression.
  • The "" glyph can be typed in Squeak by keying the underbar character (shift-hyphen).
  • Assignments are expressions; they answer the result of evaluating the right-hand-side.
  • Assignments can be cascaded as indicated above, resulting in the assignment of the same right-hand-side result to each variable.

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

  1. The message #value, sent to a block, causes the block to be executed and answers the result. The block must require zero arguments.
  2. The message #value: arg, causes the block to be executed. The block must require exactly one argument; the corresponding parameter is initialized to arg.
  3. 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

  1. 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).
  2. 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

  1. 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

  1. 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.


 

 


Welcome to the Computing  pages of Maarten Maartensz. See:  Map + Tour + Tips + Notes + News + Home