Variables and Types in Smalltalk
Learn about variables, data types, and Smalltalk pure object model - from integers and strings to symbols, characters, and type introspection
In Smalltalk, every value is an object — integers, floats, booleans, even nil and true. There are no primitive types, no special cases. This purity makes Smalltalk’s type system remarkably consistent: to find out what something is, you just ask it.
Variables in Smalltalk are dynamically typed. You declare them by name — with no type annotation — and assignment uses :=. The language is strongly typed (you cannot silently coerce a number into a string), but the type of a variable can change at runtime simply by assigning a different object to it.
In this tutorial, you will see how Smalltalk handles basic types (integers, floats, strings, booleans), Smalltalk-specific types (symbols, characters, arrays, nil), and type conversions — all through the lens of message passing.
Declaring Variables
In GNU Smalltalk scripts, variables are declared at the top with the | varName | syntax. Multiple variables can share one declaration block. Assignment uses :=. Each statement ends with . (the period is a statement separator, so the last statement may optionally omit it).
Create a file named variables_basic.st:
| |
This example demonstrates Smalltalk’s core types:
- SmallInteger — Integer values that fit in a machine word. For arbitrarily large integers, Smalltalk automatically promotes to
LargePositiveIntegerorLargeNegativeInteger. - FloatD — Double-precision floating-point. In GNU Smalltalk, float literals like
19.95are instances ofFloatD(double).FloatEandFloatQcover single and quad precision. - String — A sequence of characters, delimited by single quotes. (Double quotes are comments in Smalltalk, not strings.)
- True / False —
trueandfalseare singleton instances of the classesTrueandFalse, both subclasses ofBoolean.
The class message asks any object which class it belongs to. The name message then returns that class name as a String. This is Smalltalk reflection in its simplest form — every object knows its own type without any special operator or keyword.
Smalltalk-Specific Types
Beyond the basics, Smalltalk has several types that are central to the language’s character: symbols, characters, arrays, and nil.
Create a file named variables_types.st:
| |
Symbols
A Symbol (#name) is an interned, immutable identifier. Any two symbols with the same name are guaranteed to be the identical object in memory — #foo == #foo is always true. Symbols are used extensively as method selectors, dictionary keys, and enumeration-like constants. They respond to most String messages but cannot be modified.
Characters
A Character ($A, $x, $!) is a single-character object created with the $ prefix. Characters are not strings — they are their own class and respond to messages like asInteger (returns the ASCII code), asUppercase, asLowercase, and isLetter.
Array Literals
#(1 2 3 4 5) creates a fixed-size, ordered Array at parse time. Elements are separated by spaces, not commas. For a resizable collection, use OrderedCollection new instead. Individual elements are accessed with at: (one-based indexing):
| |
This would print 20.
nil
nil is the sole instance of UndefinedObject. It represents the absence of a meaningful value. Unlike null in many languages, nil is a full object — it responds to messages. Uninitialized variables hold nil by default.
Type Conversions
Smalltalk’s strong typing means conversions are always explicit: you send a conversion message to an object and receive a new object of the target type.
Create a file named variables_convert.st:
| |
Common conversion messages:
| Message | Effect | Example |
|---|---|---|
asFloat | Integer → FloatD | 42 asFloat → 42.0 |
truncated | Float → Integer (toward zero) | 3.9 truncated → 3 |
rounded | Float → nearest Integer | 3.5 rounded → 4 |
printString | Any object → String representation | true printString → 'true' |
asInteger | String → Integer | '99' asInteger → 99 |
asCharacter | Integer → Character (by ASCII code) | 65 asCharacter → $A |
Nothing is coerced silently. If you send a message that expects a type the object does not conform to, you get a MessageNotUnderstood error at runtime — not a quiet incorrect result.
Running with Docker
| |
Expected Output
variables_basic.st:
count = 100
price = 19.95
greeting = Hello, Smalltalk
active = true
count class = SmallInteger
price class = FloatD
variables_types.st:
Symbol: #smalltalk
Character: $S
Array: (1 2 3 4 5 )
nil: nil
Symbol class: Symbol
Character class: Character
Array class: Array
nil class: UndefinedObject
variables_convert.st:
Integer to float: 42.0
Float truncated: 3
Float rounded: 3
Integer to string: 42
String to integer: 100
Integer to character: $*
(ASCII code 42 is the * character.)
Key Concepts
- No type declarations — Variables are declared by name only (
| x |). The type is determined entirely by the object currently assigned to the variable. - Assignment uses
:=— The colon-equals operator is unambiguous and avoids confusion with the equality test message=. - Every value is a full object — There are no primitive types anywhere.
42is aSmallInt,trueis an instance ofTrue,nilis anUndefinedObject. Each responds to messages. - Symbols are interned — Any two
#nameliterals with the same spelling are the exact same object. This makes symbol identity comparison (==) both correct and efficient for use as dictionary keys or selectors. - Characters use
$prefix —$Ais the Character object for the letter A. It is not a single-character string and does not use quotes. - Type introspection is message sending —
anObject class nameretrieves the class name of any object. There is notypeofkeyword or special reflection API — it is just messages all the way down. - Conversions are explicit messages —
asFloat,asInteger,truncated,rounded,printString, andasCharacterare regular messages. No implicit coercion occurs. nilis a real object — Unlikenullin many languages,nilresponds to messages. Uninitialized variables default tonil, and sending an unrecognized message tonilraises aMessageNotUnderstooderror rather than crashing silently.
Running Today
All examples can be run using Docker:
docker pull sl4m/gnu-smalltalk:latest
Comments
Loading comments...
Leave a Comment