Reputation: 2419
I'm coding in Smalltalk using Pharo. My code:
|i delay|
i := 0.
[i < 5] whileTrue: [
[
delay := Delay forSeconds: 2.
delay wait.
Transcript show: '2 seconds are up'.
Transcript cr.
] fork.
i := i + 1.
]
It prints all the "2 seconds are up" at once, and not for each 2 seconds:
2 seconds are up
2 seconds are up
2 seconds are up
2 seconds are up
2 seconds are up
Please, can anyone tell me how to print something for each 2 seconds in Smalltalk?
Upvotes: 3
Views: 2948
Reputation: 11
[5 timesRepeat: [
(Delay forSeconds: 2) wait.
Transcript crShow: '2 secs'] .
] fork
Upvotes: 1
Reputation: 871
The answer Janko gave is certainly correct - you were forking 5 processes immediately, all of which waited the same 2 seconds, so they all completed at the same time.
Here's a bit more explanation:
[|delay|
delay := Delay forSeconds: 2.
5 timesRepeat: [
delay wait.
Transcript crShow: '2 secs']
] fork
You only have to create one Delay object, since you want to delay the same amount of time every iteration.
timesRepeat: is cleaner if you don't need the value of the index (to:do: is cleaner than whileTrue: if you DO need the index value).
Lastly, if you tried debugging this by sending the block a value message instead of the fork, you'll see a 10 second delay and then all 5 lines will be displayed. This is because the GUI is not updated while the foreground task is busy, whereas the fork causes the block to run in the background and allows the GUI (in particular the Transcript) to update.
Upvotes: 5
Reputation: 3964
You forked all 5 processes at once so that all 5 delays ends at the same time. To print every 2 seconds from the background, rather fork a whole loop in a separate process:
|i delay|
[
i := 0.
[i < 5] whileTrue: [
delay := Delay forSeconds: 2.
delay wait.
Transcript show: '2 seconds are up'.
Transcript cr.
i := i + 1]
] fork
Upvotes: 5