One suggestion I’d make here for future questions is: if you’re tempted to say “does not work,” usually some more detail would be helpful.
Most of the time, “does not work” really means “I expected it to do one thing, but it did something else.”
So it’s a good idea to a/ identify what you expected it to do and b/ describe what it did do. Without identifying these, then it’s just a completely mysterious, random, “unintuitive” phenomenon.
For example, in this case, I would guess that A/ is “I expected five values” and B/ is “it only posts 5, every time.”
This is extremely valuable troubleshooting information, not just for the people who will answer you on the forum, but also for yourself. For instance, observing that the return value of do
is the same in each of your cases, you might try 5.do
with a completely different function and observe that the return value is the same – which might lead to an inference that do
is not about return values, but rather about something else.
Background concept
In SC (as in C, Java… etc…), a function can have two types of outcome:
- Its direct return value.
- Side effects.
Here’s an example of a (dumb) function that only returns a value, and doesn’t affect anything else in the system:
(
f = { |i, divisor = 20|
i / divisor
};
)
f.(3)
-> 0.15
f.(5);
-> 0.25
5.do { |i| f.value(i); };
-> 5
5.collect { |i| f.value(i); };
-> [ 0.0, 0.05, 0.1, 0.15, 0.2 ]
We could call this a “pure function” – the only thing that matters is the output.
A little tweak gives the function a side effect:
(
z = Slider(nil, Rect(800, 200, 200, 50)).front;
f = { |i, divisor = 20|
z.value = i / divisor;
};
)
f.(3);
-> a Slider
f.(5);
-> a Slider
Now, the function’s return value is meaningless (always “a Slider”), but the slider’s position changed. The change in position is the side effect.
The rule for do vs collect is: If you are interested in the return values, use collect
. If you only need the side effects, use do
. Think “do something (and I’ll see it later)” vs “collect results, and give me all of them.”
Using the slider example:
5.do { |i| f.value(i) };
You see only one screen update – but, the slider is left at a nonzero position. do
starts counting at zero, but nonzero slider means that i
could not have remained at zero – hence the loop must have actually run to completion, just doing the updates too fast for you to see.
If you defined A = “I want to see a slider step through five positions” and B = “it jumped to the end,” then that would tell you that the problem is not that the loop didn’t run.
In the random walk case, you have both side effects (changing the value of ~currIndx
) and a return value (output ~currIndx
).
~randomWalk.value; // <= WORKS; evaluate this repeatedly!
This is printing the function’s return value.
Because you’re using the return value (and the side effect is incidental), then you want collect
. (do
throws away the return values… but you wanted the return values… so do
isn’t the right choice here.)
hjh