Smalltalk — Reference
Source: https://pharo.org/
Smalltalk
- Created: 1972 (Smalltalk-72), Xerox PARC, by Alan Kay, Dan Ingalls, Adele Goldberg and the Learning Research Group; standardized as Smalltalk-80, ANSI standard 1998 (ANSI INCITS 319-1998). This note focuses on Pharo (the most active modern lineage) with notes on Squeak, GemStone/S, VAST, and Cuis.
- Latest stable: Pharo 13.1 (June 26, 2025; Pharo 13.0 May 21, 2025). Squeak 6.0 (Jun 2022, latest at time of writing). https://pharo.org/news, https://squeak.org/
- Owner / steward: Pharo Consortium (Inria, RMOD, Lille; CNRS) for Pharo. Squeak Foundation for Squeak. Instantiations (commercial, formerly OTI/IBM) for VAST. GemTalk Systems for GemStone/S.
- Paradigms: Pure object-oriented. Everything is an object — including classes, methods, blocks (closures), and the IDE itself. Message passing is the only computational primitive.
- Typing: Dynamic, strong, latent. No static type declarations. Method dispatch is runtime by selector + receiver class.
- Memory: GC’d. Modern Pharo uses a generational scavenger + incremental mark-sweep; the Spur object format (Eliot Miranda, 2014+) is the modern object memory used by Pharo and Squeak (https://clementbera.wordpress.com/2014/01/16/spur-a-new-object-representation-for-cog/).
- Compilation: Source compiled to bytecode, executed by the Cog VM (a JIT VM written in itself via the Slang/VMMaker bootstrap; Eliot Miranda is the principal author). The VM lives in C generated from Smalltalk.
- Primary domains: Live programming, exploratory data analysis, domain modeling, software visualization (Roassal), education, business systems (GemStone/S in finance and healthcare), heavy multi-user object servers.
- Official docs: https://pharo.org/ • https://books.pharo.org/ • https://squeak.org/ • ANSI Smalltalk Standard (paywalled).
At a glance
Smalltalk is the live-image language. There is no “build → run → debug” loop because there is no separate build artifact: you work inside a running image where every object — including the compiler, the debugger, the windowing system, and your own classes — is editable while running. Pharo is the actively developed, modern, MIT-licensed flagship; Squeak is the original-PARC-team lineage (Kay, Ingalls, 1996); GemStone/S is a commercial multi-gigabyte persistent object database that’s also a Smalltalk runtime; VAST is the IBM/OTI commercial line; Cuis is a minimalist Squeak fork by Juan Vuletich. Sources: https://pharo.org/, https://squeak.org/, Goldberg & Robson, Smalltalk-80: The Language and its Implementation (Addison-Wesley, 1983).
Getting started
-
Install (Pharo): The Pharo Launcher is the canonical entry point — download images and VMs, manage multiple Pharo versions side by side. https://pharo.org/download
# Or via Zeroconf: curl https://get.pharo.org/64/130+vm | bash ./pharo Pharo.image -
No version manager analog needed: images are self-contained directories (
<name>.image,<name>.changes,<name>.sources); copy to fork. -
Hello world (Pharo Playground, Cmd-Shift-O):
Transcript show: 'Hello, Smalltalk!'; cr.Or, evaluate inline (Cmd-P, “Print it”):
'Hello, Smalltalk!'. -
Project layout: Source code lives in the image, not in files. The mapping to filesystem is done by Tonel format (Pharo’s git-friendly textual format — one method per file is not used; one class per file with method chunks): https://github.com/pharo-vcs/tonel.
-
Package & build tool: Metacello is the dependency manager (declares baselines and configurations); Iceberg is the git integration (https://github.com/pharo-vcs/iceberg).
Metacello new baseline: 'PetitParser2'; repository: 'github://kursjan/petitparser2'; load. -
REPL / live env: The Playground (scratchpad), System Browser (class navigation), Inspector (live object exploration with custom views via Phlow), Debugger (step + edit + restart on the fly), Spotter (Cmd-Shift-F, fuzzy search across everything).
Basics
-
Types & literals: Everything is an object.
42(SmallInteger),1/3(Fraction),3.14(Float),$a(Character),'hello'(String),#symbol(internedSymbol),#(1 'two' $3)(literalArray),nil,true,false,[:x | x + 1](block / closure /BlockClosure). -
Variables / scoping:
| x y |declares temporaries. Class-side instance variables, class variables, pool dictionaries, globals (Smalltalk globals). -
Control flow: All “syntax” is messages.
cond ifTrue: [...] ifFalse: [...],[cond] whileTrue: [...],1 to: 10 do: [:i | ...],coll do: [:e | ...]. There is noif/while/forkeyword. -
Methods: Three syntactic forms — unary (
obj negated), binary (a + b), keyword (dict at: 'k' put: 'v'). Method definition lives in a class:Integer >> factorial ^ self <= 1 ifTrue: [1] ifFalse: [self * (self - 1) factorial]^returns from the method; without it, the method returnsself. -
Strings: Mutable
String(immutable variants exist).'a' , 'b'for concat;'foo' asSymbolto intern. -
Collections: Rich hierarchy:
Array,OrderedCollection,Set,Dictionary,Bag,LinkedList,Interval,Stream. Polymorphic protocol —do:,collect:,select:,reject:,inject:into:(fold),detect:,count:work across all of them.
Intermediate
- Class system: Single inheritance + traits (Pharo). Every object has a class; every class is also an object (instance of its metaclass). The metaclass hierarchy mirrors the class hierarchy.
Object class superclass = Object classis not — read https://gbracha.blogspot.com/2008/12/inheritance-versus-subtyping.html and the Pharo book. - Modules / packages:
RPackage(Pharo) groups classes;BaselineOf<Name>defines a project’s structure for Metacello. Tonel format for git. - Error handling: Exceptions are first-class objects.
[risky] on: ZeroDivide do: [:ex | ex return: 0].ex pass,ex signal,ex retrygive fine control. Resumable exceptions are real —ex resume: valuecontinues from the signaling point. - Concurrency: Cooperative green threads (
Process), preempted by priority. Synchronization viaSemaphore,Mutex,Monitor,SharedQueue. The whole image is a single OS thread by default; TaskIt (https://github.com/pharo-contributions/taskit) provides futures and promise composition. Pharo 13 ships an FFI threading API for native off-image work. - I/O:
FileSystem(filesystem path/file abstraction),ZnClient(HTTP via Zinc),OSSubprocess(subprocess),Streamhierarchy.Transcriptis the system console. - Stdlib highlights:
Kernel,Collections,Files,Streams,Network(Zinc HTTP, Soup HTML parser),Tools(System Browser, Inspector, Debugger),Spec2(UI builder),Bloc(vector graphics),Roassal3(visualization),NeoJSON/STON(serialization).
Advanced
-
Memory / GC: Spur object format (one object header, indirect class refs via class table, segmented old space). Generational + mark-sweep + compactor. Pharo can grow/shrink the heap dynamically. Inspect with
Smalltalk garbageCollect,Smalltalk vm parameters. https://clementbera.wordpress.com/ -
Concurrency: As above — green threads + the FFI thread bridge. The single-image-thread model is a real constraint; for compute parallelism, spawn child Pharo images via OSProcess or use GemStone for distribution.
-
FFI: uFFI (Pharo’s modern FFI, by Esteban Lorenzano):
LibC >> abs: anInteger ^ self ffiCall: #(int abs(int anInteger)) module: 'libc'Cleaner than Squeak’s older
NBFFI. https://github.com/pharo-project/pharo/wiki/uFFI-tutorial -
Reflection (the MOP): Smalltalk has the fully reflective Meta-Object Protocol. From any object you can:
- inspect class:
obj class,obj class methodDictionary,obj class instVarNames. - read/write instance variables:
obj instVarNamed: 'foo',obj instVarNamed: 'foo' put: 42. - get the live execution context:
thisContext,thisContext sender, walk the stack. - intercept every failed dispatch: override
Object >> doesNotUnderstand: aMessage(DNU) — basis for proxies, futures, mock objects, RPC, ORM lazy loaders. - swap one object’s identity for another atomically:
oldObj becomeForward: newObjrewrites every pointer in the image.
- inspect class:
-
Performance tools:
MessageTally(sampling profiler —MessageTally spyOn: [...]),TimeProfiler,SpaceTally. The Iceberg UI shows hotspot annotations. -
Tactics / proof: N/A. Smalltalk has no static analyzer / theorem prover in the box, but the live debugger is a kind of “operational theorem prover” — change a method, restart the call frame, observe.
God mode
-
The image as a database: The
.imagefile is a memory snapshot. Save it (Smalltalk snapshot: true andQuit: false) and you have your entire dev environment, open windows and all, frozen for resume. The hardest problem in Smalltalk is source control on this binary blob — solved (uneasily) by Tonel + Iceberg. https://github.com/pharo-vcs/iceberg -
doesNotUnderstand:(DNU): Any class that overridesdoesNotUnderstand:becomes a proxy for any message. Idiomatic for futures, transparent persistence, mocks, lazy ORM:RemoteProxy >> doesNotUnderstand: aMessage ^ self transport send: aMessage selector args: aMessage arguments -
become:andbecomeForward:: Atomic identity swap. Every reference to the receiver is repointed to the argument (or vice versa) by a heap walk. Used for hot-class reshape (adding instance variables to a live class without restarting), schema migration in GemStone, and the IDE’s own “edit a class while instances of it exist” magic. -
Metaclass hierarchy: Each class is an instance of its metaclass.
Integer classisInteger class; the metaclasses form a parallel hierarchy. Class-side methods (defined “on the class side”) are instance methods of the metaclass. -
thisContext: A pseudo-variable that evaluates to the currently executing method context — the activation record, as a real object. Walk it (sender,method,pc,tempAt:) for stack traces, continuations, call/cc-style control flow, and the debugger. -
Reflective MOP — rewrite the compiler from inside:
Compileris itself a Smalltalk class with editable methods. You can install a different parser (Pharo’sOpalCompileris the default, swappable). People have prototyped new languages by replacing only the compiler and keeping the rest of the image. https://opalcompiler.gitbook.io/ -
Pragmas + method properties:
<menuItem: 'Inspect'>annotations on methods, queryable at runtime — power for everything from menu construction to declarative test runners. -
Spec / Spec2: Declarative UI builder with separate model/view/controller. Composes via subclasses, supports MVP-style presenters. https://github.com/pharo-spec/Spec
-
Iceberg (git integration): Iceberg makes git work with Tonel. Each method-edit becomes a textual diff, but the in-image edit experience is preserved. Branch switching reloads classes live. The hardest part of Smalltalk in 2025 is still git, and Iceberg is the practical answer.
-
Bloc + Brick: Pharo’s modern vector graphics framework (replacement for the old
Morphic). https://github.com/pharo-graphics/Bloc -
Roassal: Visualization framework — interactive charts, graphs, code maps. Trivial to wire to live image data. https://github.com/pharo-graphics/Roassal
-
Live (debug-driven) programming: Run a test that fails → debugger opens at the failure → write the missing method in the debugger → click “Proceed” → test goes green. The “save the world from a debugger” workflow is documented in Pharo by Example.
-
Slot model + first-class slot reflection: Pharo replaced raw instance variables with
Slotobjects — each variable is an object that can intercept reads/writes (e.g., property bindings, computed slots, validation). https://github.com/pharo-project/pharo/wiki/Slots -
Phlow: Custom inspector views per class — open an inspector on a
ZnUrl, see “Components” / “Resolved” / “HTTP Headers” tabs you defined. -
Microdown: Pharo’s lightweight markdown variant for in-image documentation, with executable code snippets that round-trip through the image.
Idioms & style
- Naming:
UpperCamelCasefor classes (OrderedCollection);lowerCamelCasefor selectors (addFirst:,at:put:); keyword selectors are one selector with multiple parts (at:put:is one method name). - Formatter / linter: Pharo ships RBFormatter (Refactoring Browser formatter) and a Quality Assistant that flags smells in real time. Uniform indentation: 1 tab per level, period at end of statement (not last in block).
- Idiomatic patterns:
- “Tell, don’t ask” — push behavior into the receiver class.
- Polymorphism over
isKindOf:checks. - Cascades (
;) for method chains on one receiver:OrderedCollection new add: 1; add: 2; yourself. - Blocks for control flow (
ifTrue:,whileTrue:) — all control is messages. - Avoid
classchecks; use double dispatch.
- What experts look for: Small methods (Smalltalkers aim for ≤ 7 lines, single responsibility); meaningful selectors that read like English; refactoring browser (Cmd-T) used heavily; tests written in SUnit (the original xUnit, https://en.wikipedia.org/wiki/SUnit); use of
assert:/deny:rather than control-flow assertions.
Ecosystem
- Pharo libraries:
- Zinc — HTTP client/server.
- NeoJSON / STON — JSON / Smalltalk Object Notation.
- Voyage — object-document mapping (Mongo, in-memory).
- Glamorous Toolkit (GT) — moldable development environment built on Pharo (https://gtoolkit.com/), arguably the most innovative Smalltalk descendant in active use.
- Seaside — continuation-based web framework (https://seaside.st/).
- TaskIt — futures.
- PetitParser — parser combinators.
- OSSubprocess — subprocess management.
- Squeak ecosystem: Etoys (kid-friendly programming env, used in OLPC), Croquet/OpenCobalt (collaborative 3D), Scratch (originally built on Squeak before its rewrite).
- Other Smalltalks:
- GemStone/S — multi-user persistent OODBMS Smalltalk (https://gemtalksystems.com/), used in finance/healthcare.
- VAST Platform (formerly VisualAge) — Instantiations, commercial, https://www.instantiations.com/.
- Cuis Smalltalk — minimalist Squeak fork by Juan Vuletich (https://cuis.st/).
- Amber Smalltalk — Smalltalk that compiles to JS, browser-runnable.
- Dolphin Smalltalk (Object Arts) — Windows-native, open-sourced 2016.
- Notable projects: Croquet (later Open Cobalt), Scratch 1.x (built on Squeak), GemStone/S in production at NYSE-derivative trading desks, Newspeak (Gilad Bracha — Smalltalk-influenced; was Smalltalk-implemented).
Gotchas
- Image-based workflow is the philosophy and the problem: if you
Smalltalk snapshotwith a broken image, your dev env is broken until you load a backup. Always commit and keep the previous.imagearound. - Git is hard: Tonel + Iceberg are good but not seamless. Merge conflicts on method-level chunks happen. Branch-per-feature with frequent commits is the safe path.
- Single-VM-thread: A blocking FFI call freezes the whole UI. Use
OSSubprocessfor blocking IO; use uFFI’s threaded variant when available. - No type system: Refactors that would be safe in Java/Haskell can break callers silently. SUnit coverage is the only safety net — invest heavily.
become:is dangerous and slow: It walks the heap. Don’t call it in tight loops.- Reflection makes things possible that probably should not be done:
doesNotUnderstand:proxies can hide real bugs (typos in selector names look like proxy hits). Use sparingly. - DNS-of-source: A method’s source code is stored in
.changes/.sources; corrupting these makes “view source” return<source missing>even though execution still works (bytecode is in the image). - VM/image version skew: A Pharo 13 image needs a Pharo 13 VM. The Pharo Launcher prevents most mistakes; manual installs do not.
- ANSI standard ≠ what’s in the image: The 1998 ANSI Smalltalk standard is a baseline; every implementation extends it differently. Portable code uses only the ANSI subset, which is small.
- Squeak vs Pharo divergence: Pharo aggressively cleaned up Smalltalk-80 inheritance for modernity; many Squeak idioms (Morphic UI, certain class names) differ. Don’t assume cross-compat.
- Cmd shortcuts vs Ctrl: macOS uses Cmd, others use Ctrl/Alt — older docs assume macOS bindings.
Citations
- https://pharo.org/ — Pharo home.
- https://pharo.org/news — Pharo 13.0 (2025-05-21) and 13.1 (2025-06-26) announcements.
- https://books.pharo.org/ — Pharo by Example, Deep into Pharo, Pharo Enterprise, Numerical Methods with Pharo.
- https://github.com/pharo-vcs/iceberg — git integration.
- https://github.com/pharo-vcs/tonel — Tonel source format.
- https://github.com/pharo-graphics/Bloc — Bloc graphics.
- https://github.com/pharo-graphics/Roassal — Roassal visualization.
- https://github.com/pharo-spec/Spec — Spec UI.
- https://github.com/pharo-project/pharo/wiki/uFFI-tutorial — uFFI.
- https://github.com/pharo-project/pharo/wiki/Slots — first-class slots.
- https://squeak.org/ — Squeak (latest 6.0).
- https://gtoolkit.com/ — Glamorous Toolkit.
- https://seaside.st/ — Seaside web framework.
- https://gemtalksystems.com/ — GemStone/S.
- https://www.instantiations.com/ — VAST.
- https://cuis.st/ — Cuis Smalltalk.
- Goldberg & Robson, Smalltalk-80: The Language and its Implementation, Addison-Wesley, 1983.
- ANSI INCITS 319-1998 — ANSI Smalltalk standard.
- https://clementbera.wordpress.com/2014/01/16/spur-a-new-object-representation-for-cog/ — Spur object format.