Smalltalk Syntax Cheat Sheet

Aus expecco Wiki (Version 2.x)
Version vom 9. Mai 2025, 20:17 Uhr von Cg (Diskussion | Beiträge) (→‎Standard)
(Unterschied) ← Nächstältere Version | Aktuelle Version (Unterschied) | Nächstjüngere Version → (Unterschied)
Zur Navigation springen Zur Suche springen

A short, one page summary of what beginners need to know about Smalltalk/X, its syntax and most useful code fragments.
As usual, this is only a tiny fraction of what is really awailable, and you should use the builtin class browser to find many more useful functions in the system.

This page was extracted from the "Smalltalk/X Programmers guide - Smalltalk/X Cheat Sheet".
Smalltalk/X language extensions (w.r.t. other Smalltalk implementations) are marked with (*).

Smalltalk Philosophy[Bearbeiten]

  • The world consists of objects which communicate by sending messages.
A message looks like an english sentence, and might look like "heyYou doSomething".
In this example, the "heyYou" is called the "receiver of the message"
You may pass additional parameter objects (arguments) as in: "heyYou doSomethingWith: arg"
or multiple arguments as in "heyYou doSomethingWith: arg1 and: arg2"
In these examples, the "heyYou" is called the "receiver of the message"
  • Messages without argument are called "unary messages"; those with arguments are called "keyword messages"
For example "Transcript clear" (sends the message "clear" to the Transcript object),
and "Transcript show: 'hello'" (sends the message "show:" to the Transcript, passing a string argument),
  • To allow for arithmetic operations, any non-letter character (except for a few) are treated like a message name and written between the receiver and the one and only argument. These are called "binary messages".
For example: "3 + 4" or "abc , def" (yes, the comma is an operator; it does string concatenation)
  • The object my respond (or "answer") by returning some result object. In the above example, "3+4" would answer "7", and "'hello' , 'world'" would answer 'helloworld'
  • binary messages have no meaning to the compiler; they are all equal and simply evaluated from left to right.
admitted, this makes arithmetic a little strange initially; you'll need parentheses as the is not precidence of eg. * over +. The expression "3 + 4 * 5" will be evaluated left to right and answer 35.
  • Everything in this world is an object;
from low level things like booleans, true, false, integer numbers, floating point numbers characters etc.
there are containers, which can hold on other objects. Technically, all such references are via pointers.
there are also very complex objects and structures which implement windows, the user interface, communication interfaces, debuggers and even compilers which allow for code to be defined and installed on the fly.
  • Every object is associated to a class. Classes define the behavior of their instances. I.e. they define how they respond to messages. The response is implemented by a so called method. That is a piece of code which is executed when a message comes in. A method consist of a number of statements (which are message sends), each separated by a full stop (as in english).
  • Classes are themself objects, which respond to messages. Typically class messages would answer new instances, constants or utility functionality. There are also class messages to create new classes.
  • Class can inherit common functionality (i.e. method implementations) from a superclass. Thus creating a hierarchy of classes. Typical hierarchies are the Number hierarchy, Collections, Streams and UI Widgets.
  • In Smalltalk, every behavior is defined by corresponding message implementations. This includes control features (i.e. if-then-else, loops and exception handling). All of them are implemented as messages being sent to booleans (ifTrue:/ifFalse:) or blocks (whileTrue:)
  • Blocks are special objects, which wrap a piece of code. Other languages know them as anonymous functions or lambdas or closures. But the Smalltalk syntax makes them super easy to use: just write a number of expressions inside square brackets, as in "[ Transcript show: 10 factorial ]".
blocks can be passed as argument with a message send; for example to a boolean: "aBoolean ifTrue: [ Transcript show: 'yes' ]"
blocks can be stored in variables and passed arounf just like any other object
blocks can receive messages, especially loop messages: "[ a < 10] whileTrue:[ Transcript showCR: a. a := a + 1 ]".

Syntax[Bearbeiten]

Comments[Bearbeiten]

Regular comment " this is a comment " any text between double quotes
EOL-Comment (*) "/ this is an End-of-Line comment text from quote-slash to line end
Token-Comment (*) "<<END
a multiline token-comment up to
a line starting with 'END'
more commented stuff here
...
comment ends here
END
text up to line beginning with whatever token came
after the initial "<<"

Literal Constants[Bearbeiten]

Numbers[Bearbeiten]
Integers 12345
-12345
Large integers 1234567890123456789012345 arbitrary number of digits
Integers with radix
(Smalltalk style)
16rAFFE, 2r010101, 8r0777, 3r012012,
16r-AFFE, 2r-010101
prepend the radix (base)
any radix from 2..36 is possible (i.e. 3r222 is a ternary number)
Integers with radix
(C style) (*)
0xFEED
-0xBEAF
0b11011,-0b1100
C/Java/JavaScript style: prepend radix indicator ('x', 'b', 'o')
One of hex, binary and octal
Floats
(IEEE double; roughly 17 digits)
12.456
1.234e17
-6.9
-6e-10
Float pi
Float e
called "Float", but actually hold double precision
Common constants can be referred to "by name".
Short floats
(IEEE single; roughly 8 digits) (*)
1.234f17
-6f-10
this is controlled by a ParserFlag (singlePrecisionFloatF), which is currently defaulted to false. Thus, by default, double precision floats are created with the 'f' exponent character.
Long floats
(IEEE quad; roughly 20 digits) (*)
1.234q17
-6q-10
actual precision depends on the underlying CPU
(on x86/x86_64: only 80bit)
Quad floats;
roughly 34 digits (*)
1.234Q17
-6Q-10
computed in software; therefore slower; this is not yet officially released.
Large floats;
roughly 60 digits (*)
1.234QL17
-6QL-10
computed in software; therefore slower; this is not yet officially released.
Fractions (1/3)
(17/2)
ScaledDecimals 1234.53s2 the number after the s specifies the number of digits
Characters and Strings[Bearbeiten]
Characters $a
Character space
Character nl
Also: "null", "tab", "return", "bell"...
Or:
Character codePoint:n
traditionally, Smalltalk does not support any escape sequence
Common constants can be referred to "by name".
Strings 'hello' traditionally, Smalltalk does not support any escape sequence inside
(I.e. they are what Python calls Raw Strings)
But see below...
Strings
(C Style) (*)
c'hello\nworld' supports the common escape sequences, such as "\n", "\t", "\xHH"
Strings
(With Embedded Expressios) (*)
e'hello {OperatingSystem getLoginName}' expressions in braces are evaluated at runtime and sliced into the string (also a C-string)
Strings
(Language translated with Embedded Expressios) (*)
i'hello {OperatingSystem getLoginName}' like above, but the string is also possibly translated to a national language
Symbols #'hello'
#foo
without quotes, if only alphaNumeric characters
Arrays and Objects[Bearbeiten]
Arrays
#( el1 el2 ... elN ) each element is a literal constant
Byte Arrays #[ b1 b2 ... bN ] each byte-element an integer constant in 0..255
Special Number Arrays (*) #XX( v1 v2 ... vN ) XX: is one of
 'u8', 's8', 'u16', 's16', 'u32', 's32', 'u64', 's64', 'f32', 'f64'
 and each element being an integer or float constant
Immediate Inline Objects (*) #{ foo: fooValue . bar: barValue } fooValue and barValue: are constants

Lambda Blocks (Closures)[Bearbeiten]

Without argument [ expr1 . expr2 ... exprN ] multiple expressions sep'd by period.
When evaluated, the value is the value
from the last expression, exprN
One argument [ :arg |
    expr1 . expr2 ... exprN
]
Multiple arguments [ :a1 :a2 ... :aN |
    expr1 . expr2 ... exprN
]
Local Variables inside a block [ :a1 ... :aN |
     |local1 local2 |
     expr1 ... exprN
]

Expressions[Bearbeiten]

Unary Expression
(without argument)
receiver messageName receiver is itself either a constant, a lambda-block, a unary expression
or a parenthesized expression
Keyword Expression
(1 arg)
receiver messageNamePart:argExpression whitespace between the colon and the argExpression is optional.
Keyword Expression
(any number of args)
receiver
    messageNamePart1:argExpression1
    messageNamePart2:argExpression2
    ...
    messageNamePartN:argExpressionN
Binary Expression receiver binOP arg with binOP being any combination of special characters:
* , + , - , % , & , / , \ , | , = , < , > , ? and ,


I.e. "foo ==> 123" is the binary message "==>" sent to foo with 123 as argument.
And "foo ? 123" is the binary message "?" sent to foo with 123 as argument.

Cascade Expression
(multiple messages to the same receiver)
receiver
    message1 ;
    message2 ;
    ...
    messageN
the receiver expression is evaluated,
then multiple messages (separated by ";") are sent to this receiver.
Parentheses for grouping ( any expression )
Assignment variable := expression can be used as expression.
Computed Array (Brace Construct) (*) { expr1 . expr2 . ... . exprN } instantiates a new Array object with elements from the expressions.
Computed Inline Object (*) { foo: fooExpr . bar: barExpr } fooExpr and barExpr: expressions
Inline string expressions (*) e'p1{e1}p2{e2}...pN{eN}pM' syntactic sugar for:
('p1%1p2%2...pN%NpM' bindWith:e1 with:e2 ... with:eN)
where each pI is a string with possible C-escapes
and each eI is a Smalltalk expression
Array Indexing (*) coll[idx]
coll[idx1][idx2]
coll[idx1][idx2][idx3]
syntactic sugar for:
(coll at:idx)
where coll must be an indexable collection,
and idx of compatible index type.
I.e. integer for array-like collections, hash-key for dictionaries, etc.
Up to 4 dimensions are (currently supported)
Collection instantiation (*) someClass[sz]
someClass[sz][sz]
...
syntactic sugar for:
(someClass new:sz)
where someClass must be a collection class
I.e. Array[10] creates an empty array with 10 slots.
1, 2, 3 and 4 dimensions are supported

Remaining Syntax[Bearbeiten]

Local variables (in block or method) | var1 var2 ... varN | variable declarations must be at the beginning, before any expression.
Separating multiple expressions (sequence) expr1 . expr2 . ... exprN expressions (statements) are separated by fullstop (period) characters.
The last expression may or may not be followed by a fullstop;
if there is one, this is treated like a followup empty statement.
Return from method ^ expression returns from the enclosing method (also if inside a block-closure)

Wellknown (Common) Messages[Bearbeiten]

Conditional Execution boolExpr1 ifTrue:[ ... ] ifFalse:[ ... ] variations without true-part, without false part
and with the order reversed are available.
While-Loop
(test at top)
[ boolExpr1 ] whileTrue:[ ... ] notice the receiver being a block.
A whileFalse: variant is also available.
Do-Loop
(test at bottom)
[ ... ] doWhile:[ boolExpr1 ] notice the test being a block.
A doUntil: variant is also available.
For-Loop start to:stop do:[:iterVar | ... ] evaluates the block (lambda) for each value in start..stop.
Enumerating Collections collection do:[:elementVar | ... ] evaluates the block (i.e. lambda) for each element in the collection.
Evaluating a Lambda Block
  without arguments:

  with arguments:


aBlock value

aBlock value:expr1 ... value:exprN

the number of arguments must match the number expected by the lambda
(although varArg lambdas are also available)
Exception Handling [ ... ] on:Error do:[:ex | ... ] evaluates the first block;
if an error is encountered, evaluate the handler

Special 'Control Structures'[Bearbeiten]

Starting another Thread p := [ ... ] fork the code inside the block will execute in a separate thread
Creating, configuring and starting another Thread p := [ ... ]
  newProcess;
  name:'my worker';
  priority:5;
  resume
the code inside the block will execute in a separate thread
Terminating a Thread p terminate with p referring to the thread as created by newProcess or fork
Interrupting a Thread p interruptWith:[ ... ] interrupt the thread and let it execute the given code (in its interrupt seervice)
Exception Handling [ ... ]
  on:Error do:[:ex |
    ...
  ]
the handler will get an exception argument (ex), which contains additional information, and can be told how to deal with the error
Exception Handling - proceeding [ ... ]
  on:Error do:[:ex |
    ...
    ex proceed
  ]
proceed, as if the error did not happen
Exception Handling - restarting [ ... ]
  on:Error do:[:ex |
    ...
    ex restart
  ]
restart the code from the beginning (usually after the handler did some cleanup, such as lazy loading a missing file...)
Exception Handling - printing [ ... ]
  on:Error do:[:ex |
    ...
    ex description
    ...
  ]
contains a human readable description of the error
Ensure/Unwind Protect [ ... ]
  ensure:[
  ...
  ]
the ensure block will be evaluated in any case
Ensure/Unwind Protect [ ... ]
  ifCurtailed:[
  ...
  ]
the ifCurtailed block will be evaluated only on a non-regular exit
(i.e. when an exception was raised, or the operation was aborted or the thread terminated)
Early exit from Loops [:exit |
  ...
  code with loop
  ...
  exit value
  ...
] valueWithExit
the block will be left, when exit is evaluated. Often used as argument of ifTrue:, as in
cond ifTrue: exit
Queries Query
  answer:something
  do:[
    ...
    Query query
    ...
  ]
to provide answers way down to whoever is interested.
Queries answer nil if no one is there to answer.
Queries are usually more specifically used as subclasses of Query
Notifications Notification
  handle:[
    ...
  ]
  do:[
    ...
    Notification notify:someArg
    ...
  ]
to provide information way up to whoever is interested
Notifications are usually more specifically used as subclasses of Notification
Observers 1 foo onChange:#bla evaluate:[...].
...
foo changed:#bla
observer with generic block to evaluate
Observers 2 foo onChangeSend:#xyz to:someone.
...
foo changed
observer with message send
Observers 3 foo addDependent:someone.
...
foo changed
observer with send to update method of target

Queries and Notifications can be seen as observers within the calling hierarchy (i.e. information flows up or down the calling hierarchy), whereas the dependency and anChange mechanisms are independent of the control flow (even between different threads)

Synchronization and Timers[Bearbeiten]

Timed Delay Delay waitForSeconds:n
Delay waitUntil:(Timestamp now + 10 seconds)
self explaining
Sempaphore wait s := Semaphore new.
...
s wait.
...
s signal
obviously, the signalling must be evaluated by another thread
Sempaphore wait with timeout s := Semaphore new.
...
s waitWithTimeout:(5 seconds).
...
s signal
obviously, the signalling must be evaluated by another thread
Multi Sempaphore wait s1 := Semaphore new.
s2 := Semaphore new.
...
which := (s1 , s2) wait.
...
s2 signal
wait for any of multiple semaphores
Synchronized Collections a := OrderedCollection new asSharedCollection will wrap the collection so that add/remove operations are atomic

Wellknown Globals[Bearbeiten]

Logging and Messaging Transcript - the console window
Stdout - standard output
Stderr - standard error
Stdin - standard input
Logger - redefinable logger (defaults to standard error)
Common Useful Dialogs Dialog - provides many useful utility functions for standard dialogs
eg.
Dialog warn:'message'
Dialog confirm:'question'
Dialog request:'question'
Dialog requestFilename:'question'
...

Most Wellknown Classes[Bearbeiten]

Numbers Number(abstract superclass)
Integer(integral numbers)
Float(inexact)
Fraction(exact)
Complex
Collections Array (fixed size array)
OrderedCollection, List (variable size)
SortedCollection
Set, Bag (unordered)
Dictionary (mapped collections)
BinaryTree, AVLTree
SharedQueue (shared, synchronized)
many more...
Process Handling Process (lightweight thread)
OSProcess (heavyweight OS process)
Semaphore, RecursionLock (synchronization)
Monitor, BoltLock
Delay (time delays)
Files & Streams Filename (file naming, directory access, mime type)
Stream (basic stream framework)


ReadStream,WriteStream,EncodedStream
ExternalStream, FileStream, Socket, PipeStream (OS-cmd streams)

Low Level Access OperatingSystem (OS API calls)
Smalltalk(startup, shutdown and globals)
ObjectMemory(VM access)

Examples[Bearbeiten]

exampleMethod1
    |v1 v2|

    v1 := 42.
    v2 := v1 sqrt.
    Transcript showCR: 'the root of the answer to all questions is: %1' with: v2.

using expanded strings, this can be written as:

exampleMethod1_alternative
    |v1|

    v1 := 42.
    Transcript showCR: e'the root of the answer to all questions is: {v1 sqrt}'.

enumerating elements of an array:

exampleMethod2
    |arr|

    arr := #( 1 2.0 'three' (4 4 4 4) ).
    arr do:[:el |
        Transcript showCR: el
    ]

enumerating elements of an array with additional index:

exampleMethod3
    |arr|

    arr := #( 1 2.0 'three' (4 4 4 4) ).
    arr doWithIndex:[:el :idx |
        Transcript showCR: e'array element at {idx} is {el} and its class is {el class name}\n'
    ]

dialogs, string-to-number conversion, error handling:

exampleMethod4
    |s1 nr1 s2 nr2 rslt|

    s1 := Dialog request:'Enter the first number' initialAnswer:1.
    s1 isNil ifTrue:[ ^ self ].   "/ cancelled - return from method
    s2 := Dialog request:'Enter the second number' initialAnswer:2.
    s2 isNil ifTrue:[ ^ self ].   "/ cancelled - return from method

    "/ convert; on error return from method
    nr1 := Number readFrom:s1 onError:[^ self].
    nr2 := Number readFrom:s2 onError:[^ self].

    "/ save division
    [
        rslt := nr1 / nr2
    ] on: Error do:[:ex |
        (Dialog confirm: e'Error encountered: {ex description}\nProceed with zero?')
            ifFalse:[^ self]. "/ no; return from method
        ex proceedWith:0
    ].

    Dialog information: e'the result is {rslt}'

dialogs, error handling and complex square root:

exampleMethod4
    |s nr rslt|

    s := Dialog request:'Enter a number (may be negative)' initialAnswer:2.
    s isNil ifTrue:[ ^ self ].   "/ cancelled - return from method

    "/ convert; on error return from method
    nr := Number readFrom:s onError:[^ self].

    "/ square root; catch imaginary result
    [
        rslt := nr sqrt
    ] on: ImaginaryResultError do:[:ex |
        (Dialog confirm: e'No solution in R; want to see the complex result?')
            ifFalse:[^ self]. "/ no; return from method
        rslt := Number trapImaginary:[ nr sqrt ].
        "/ rslt is now a complex number
    ].

    Dialog information: e'the result is {rslt}'

Standard[Bearbeiten]

The ANSI Smalltalk standard was approved on May 19, 1998. The official name of the document is ANSI INCITS 319-1998 (R2002). You can order a copy of the final standard from here: [1] or here [2]. The name of the document is "American National Standard for Information Systems - Programming Languages - Smalltalk".

You can also download the final draft revision for free: standard_v1_9-indexed.pdf and at [3].

The final draft is identical to the official standard except that the draft also has a rationale included (and thus, the draft is arguably more useful than the official standard).


Protocol from ANSI Meeting: [4]



Copyright © 2014-2024 eXept Software AG