Understanding Smalltalk control structures

TL;DR

This page gives a high-level overview of how control structures in Smalltalk are all implemented by messages sent to objects.

Overview

Smalltalk has no built-in control structures. Instead, all control structures are realized by sending messages to objects, usually Booleans, Integers and Collections.

We will show a few examples here, but please note that the list is open-ended: you can always add new control structures as needed.

Simple conditionals

The most basic control structures are messages sent to Booleans .

An if-then-else is just an #ifTrue:ifFalse: message sent to a Boolean value.

Date today weekday = 'Friday'
	ifTrue: [ 'Clock out early!' ]
	ifFalse: [ 'Work till closing' ]
  

Note that the arguments to #ifTrue:ifFalse: must be blocks , so they will only be conditionally evaluated.

There are also a few variants of this method, such as #ifTrue: (with an else case), #ifFalse: (without a then case), and so on. See the controlling methods of the Boolean Object subclass: #Boolean instanceVariableNames: '' classVariableNames: '' package: 'Kernel-Objects' class for other methods.

Loops

A for-loop in Smalltalk can be realized by sending #to:do: to a number.

n := 1.
1 to: 10 do: [ :i | n := n * i ].
n
  

Note that this is equivalent to sending #do: to an Interval:

n := 1.
(1 to: 10) do: [ :i | n := n * i ].
n
  

A while-loop , on the other hand, is a message to a block:

n := 1.
i := 0.
[ i < 10 ] whileTrue: [ 
	i := i + 1.
	n := n * i ].
n
  

Note that the receiver of #whileTrue: must be a block rather than simply an expression, as it needs to be reevaluated on each iteration!

Iterators

You can iterate over any collection by sending it the #do: message:

n := 1.
#(1 2 3 4 5 6 7 8 9 10) do: [ :i | n := n * i ].
n
  

But #do: is probably the least interesting message you can send to a collection.

(1 to: 10)
	inject: 1
	into: [ :product :each | product * each ]
  

The #inject:into: message takes an initial value and a two-argument block as arguments, and iteratively applies the block the initial value with each element of the collection. This is commonly known as reduce or fold in other languages.

For many more examples, have a look at Working with collections in Pharo.