LESSON 0002 · Collections & blocks · Pharo course
Lesson 0002 — Data Fluency
A real app is mostly data moving through transformations. In Pharo that means blocks sent to collections. Six selectors carry almost all of it.
Counter a new trick that uses one.
Square brackets make a block — a chunk of code saved for later, as a value you can pass around. Nothing inside runs until you send it value.
(Pharo MOOC, blocks & iteration)
[ 2 + 2 ] value → 4
[ :x | x * x ] value: 6 → 36 ":x is a parameter"
This matters because every loop in Pharo is just a message that takes a block. There is no for keyword — there’s do:.
Recognise them by what shape comes back. All verified live in your image:
#(1 2 3 4 5) do: [ :e | Transcript show: e printString ] "side effects → returns the collection"
#(1 2 3 4 5) collect: [ :x | x * x ] → #(1 4 9 16 25) "same size, transformed (map)"
#(1 2 3 4 5) select: [ :x | x even ] → #(2 4) "keep matches (filter)"
#(1 2 3 4 5) reject: [ :x | x even ] → #(1 3 5) "drop matches"
#(3 1 4 1 5 9) detect: [ :x | x > 3 ] → 4 "first match"
(1 to: 100) inject: 0 into: [ :sum :e | sum + e ] → 5050 "fold to one value (reduce)"
inject:; the block is [ :accumulator :each | ... ]. It carries a running total across the collection.
a. #(1 2 3 4) collect: [ :x | x + 1 ]
#(2 3 4 5)
collect: transforms each element; same size comes back.
b. #(1 2 3 4 5 6) select: [ :x | x > 3 ]
#(4 5 6)
select: keeps only elements whose block answers true.
c. (1 to: 4) inject: 1 into: [ :a :e | a * e ] (note the seed is 1)
24
Running product: 1·1·2·3·4 = 24. That’s 4 factorial — inject:into: is how you fold a list into one number.
d. What message-type is inject:into:, and how many arguments does its block take?
keyword; two args
One keyword message #inject:into: with two arguments (seed, block). The block itself takes two parameters: accumulator and each.
Step 1. Add a method to Counter that bumps the count once for every number in a collection — reusing your own incrementBy::
addAll: aCollection
aCollection do: [ :each | self incrementBy: each ]
Step 2. Predict, then evaluate in a Playground:
Counter new addAll: #(10 20 30); count
60
Starts at 0, then do: sends incrementBy: 10, incrementBy: 20, incrementBy: 30. The cascade’s value is the last message, count.
Step 3. Add a test testAddAll to CounterTest in your usual style (self assert:equals:) proving it lands on 60.
Then say “done” — I’ll read addAll: through Iris, run CounterTest, and give feedback.
addAll: with inject:into: instead of do: — hint: fold the collection to a total, then set count. Ask me to compare the two styles.
This week: Pharo MOOC — the “Collections” and “Blocks” videos. Reference alongside: Collections & Blocks card and the deeper treatment in Pharo by Example.
Want to see any of these run on different data, or unsure why a shape comes back? Ask me — I’ll eval it in your image instantly.