Smalltalk Examples

Smalltalk syntax highlighting

Smalltalk Code Example

Basic Syntax

Example:

"This is a comment"

"Assignment"
x := 42.
name := 'Alice'.

"Pseudo-variables"
self initialize.
super doSomething.
result := true.
value := false.
object := nil.

Messages

Example:

"Unary messages (no arguments)"
object initialize.
collection size.
number squared.

"Binary messages (one argument, operator-like)"
3 + 4.
10 - 5.
6 * 7.
20 / 4.
x < y.
a = b.

"Keyword messages (one or more arguments with colons)"
array at: 1.
dictionary at: key put: value.
collection do: [:each | each printString].

Blocks (Closures)

Example:

"Simple block"
[3 + 4] value.

"Block with arguments"
[:x | x * 2] value: 5.

"Block with multiple arguments"
[:x :y | x + y] value: 3 value: 4.

"Blocks as control structures"
x > 0 ifTrue: [Transcript show: 'positive'].
x > 0 ifFalse: [Transcript show: 'not positive'].
x > 0 
	ifTrue: [Transcript show: 'positive']
	ifFalse: [Transcript show: 'not positive'].

Temporary Variables

Example:

"Single temporary variable"
| temp |
temp := 42.

"Multiple temporary variables"
| x y result |
x := 10.
y := 20.
result := x + y.

Method Definition

Example:

"Unary method"
initialize
	super initialize.
	collection := OrderedCollection new.

"Binary method"
+ aNumber
	"Add two numbers"
	^ value + aNumber value.

"Keyword method (one argument)"
at: index
	"Return the element at the given index"
	^ collection at: index.

"Keyword method (multiple arguments)"
at: index put: anObject
	"Set the element at the given index"
	collection at: index put: anObject.
	^ anObject.

"Method with temporary variables"
factorial: n
	| result |
	result := 1.
	2 to: n do: [:i | result := result * i].
	^ result.

Collections

Example:

"Array literals"
#(1 2 3 4 5).
#('one' 'two' 'three').

"Creating arrays dynamically"
Array new: 10.
Array with: 1 with: 2 with: 3.

"OrderedCollection"
| collection |
collection := OrderedCollection new.
collection add: 'first'.
collection add: 'second'.
collection add: 'third'.

"Dictionary"
| dict |
dict := Dictionary new.
dict at: 'name' put: 'Alice'.
dict at: 'age' put: 30.
dict at: 'name'.

"Set"
| set |
set := Set new.
set add: 1.
set add: 2.
set add: 1.  "Duplicate ignored"

Iteration

Example:

"do: - iterate over elements"
#(1 2 3 4 5) do: [:each | Transcript show: each printString; cr].

"collect: - transform elements"
#(1 2 3 4 5) collect: [:each | each * 2].

"select: - filter elements"
#(1 2 3 4 5 6) select: [:each | each even].

"reject: - inverse filter"
#(1 2 3 4 5 6) reject: [:each | each odd].

"detect: - find first matching element"
#(1 2 3 4 5) detect: [:each | each > 3].

"inject:into: - reduce/fold"
#(1 2 3 4 5) inject: 0 into: [:sum :each | sum + each].

Control Structures

Example:

"Conditionals"
x > 0 ifTrue: [Transcript show: 'positive'].
x = 0 ifTrue: [Transcript show: 'zero'].
x < 0 ifTrue: [Transcript show: 'negative'].

x > 0
	ifTrue: [Transcript show: 'positive']
	ifFalse: [Transcript show: 'not positive'].

"Loops - timesRepeat:"
10 timesRepeat: [Transcript show: 'Hello'; cr].

"Loops - to:do:"
1 to: 10 do: [:i | Transcript show: i printString; cr].

"Loops - to:by:do:"
0 to: 100 by: 10 do: [:i | Transcript show: i printString; cr].

"Loops - whileTrue:"
| i |
i := 1.
[i <= 10] whileTrue: [
	Transcript show: i printString; cr.
	i := i + 1
].

"Loops - whileFalse:"
[i > 0] whileFalse: [
	Transcript show: i printString; cr.
	i := i + 1
].

Class Definition

Example:

"Defining a new class"
Object subclass: #Person
	instanceVariableNames: 'name age'
	classVariableNames: ''
	package: 'MyApp-Model'.

"Instance methods"
Person>>name
	^ name.

Person>>name: aString
	name := aString.

Person>>age
	^ age.

Person>>age: aNumber
	age := aNumber.

Person>>initialize
	super initialize.
	name := ''.
	age := 0.

Person>>printOn: aStream
	super printOn: aStream.
	aStream
		nextPutAll: ' (';
		nextPutAll: name;
		nextPutAll: ', age ';
		print: age;
		nextPut: $).

"Class methods"
Person class>>named: aString aged: aNumber
	^ self new
		name: aString;
		age: aNumber;
		yourself.

Cascades

Example:

"Multiple messages to same receiver"
Transcript
	show: 'Hello';
	space;
	show: 'World';
	cr.

"Creating and initializing objects"
person := Person new
	name: 'Alice';
	age: 30;
	yourself.

"Building complex structures"
stream := WriteStream on: String new.
stream
	nextPutAll: 'Name: ';
	nextPutAll: person name;
	nextPutAll: ', Age: ';
	print: person age.

Exception Handling

Example:

"Basic exception handling"
[
	"Code that might fail"
	collection at: index
] on: Error do: [:ex |
	Transcript show: 'Error: ', ex messageText; cr
].

"Ensure - always execute cleanup"
[
	file := FileStream fileNamed: 'data.txt'.
	file contents
] ensure: [
	file ifNotNil: [file close]
].

"ifCurtailed - execute if block exits abnormally"
[
	"Some operation"
] ifCurtailed: [
	"Cleanup code"
].

Streams

Example:

"Reading from a stream"
| stream |
stream := ReadStream on: 'Hello World'.
stream next.       "Returns $H"
stream next: 5.    "Returns 'Hello'"
stream upToEnd.    "Returns ' World'"

"Writing to a stream"
| stream |
stream := WriteStream on: String new.
stream nextPut: $H.
stream nextPutAll: 'ello'.
stream space.
stream nextPutAll: 'World'.
stream contents.   "Returns 'Hello World'"

"Building strings"
String streamContents: [:stream |
	stream
		nextPutAll: 'The answer is ';
		print: 42
].

Metaprogramming

Example:

"Reflection - inspecting objects"
object class.
object class name.
object class superclass.
object class allInstVarNames.
object class allSelectors.

"Dynamic method invocation"
object perform: #initialize.
object perform: #at: with: 1.
object perform: #at:put: with: 1 with: 'value'.

"Testing capabilities"
object respondsTo: #initialize.
object class includesSelector: #initialize.

"Creating classes dynamically"
Object subclass: #DynamicClass
	instanceVariableNames: 'slot1 slot2'
	classVariableNames: ''
	package: 'MyPackage'.

"Compiling methods at runtime"
DynamicClass compile: 'slot1 ^ slot1'.
DynamicClass compile: 'slot1: anObject slot1 := anObject'.

Advanced Examples

Example:

"Fibonacci sequence"
fibonacci: n
	n <= 1 ifTrue: [^ n].
	^ (self fibonacci: n - 1) + (self fibonacci: n - 2).

"Quicksort"
quicksort: aCollection
	| pivot less greater |
	aCollection size <= 1 ifTrue: [^ aCollection].
	pivot := aCollection first.
	less := aCollection allButFirst select: [:each | each <= pivot].
	greater := aCollection allButFirst select: [:each | each > pivot].
	^ (self quicksort: less), (Array with: pivot), (self quicksort: greater).

"Binary search"
binarySearch: anArray for: aValue
	| low high mid |
	low := 1.
	high := anArray size.
	[low <= high] whileTrue: [
		mid := (low + high) // 2.
		(anArray at: mid) = aValue ifTrue: [^ mid].
		(anArray at: mid) < aValue
			ifTrue: [low := mid + 1]
			ifFalse: [high := mid - 1]
	].
	^ nil.

"Observer pattern"
Object subclass: #Subject
	instanceVariableNames: 'observers'
	classVariableNames: ''
	package: 'Patterns'.

Subject>>initialize
	super initialize.
	observers := OrderedCollection new.

Subject>>addObserver: anObserver
	observers add: anObserver.

Subject>>removeObserver: anObserver
	observers remove: anObserver ifAbsent: [].

Subject>>notifyObservers
	observers do: [:each | each update: self].