The problem is with depth-first processing (as used by Pd) and the related stack-unrolling, as this might lead to setting the 2nd input of [select]
to an old value (which you didn't expect).
Example
Note: select:in0
means the left-most inlet of [select]
,... The numbers generated by [random]
are shown in bold (1
) and the numbers output the patch are shown in bold italics (e.g. 3
)
Imagine the [select]
is initialized to 0
and the [random 3]
object outputs a list 2 0 0 2 0 2 ...
(hint: [seed 96(
).
The expected output would be 2 0 2 0 2 ...
, however the output really is 2 0 2 2 2 ...
Now this is what happens if you consecutively send [bang(
to the random generator:
random
generates 2
2
is sent to the sel:in0
, which compares it to 0
(no match)
- and sends it out of
sel:out1
(the reject outlet), displaying the number 2
- after that the number is sent to
sel:in1
, setting it's internal state to 2
.
random
generates 0
0
is sent to the sel:in0
, which compares it to 2
(no match)
- and sends it out of
sel:out1
, displaying the number 0
- after that the number is sent to
sel:1
, setting it's internal state to 0
.
random
generates 0
0
is sent to the sel:in0
, which compares it to 0
(match!)
- and sends a bang through
sel:out0
(the match outlet)
- triggering a new call to
random
, which now generates 2
2
is sent to the sel:in0
, which compares it to 0
(no match)
- and sends it out of
sel:out1
, displaying the number 2
- after that the number is sent to
sel:1
, setting it's internal state to 2
.
- after that the number
0
(still pending in the trigger:out0
) is sent to sel:1
, setting it's internal state to 0
!!!
random
generates 0
0
is sent to the sel:in0
, which compares it to 0
(match!)
- and sends a bang through
sel:out0
- triggering a new call to
random
, which now generates 2
2
is sent to the sel:in0
, which compares it to 0
- and sends it out of
sel:out1
, displaying the number 2
- after that the number is sent to
sel:1
, setting it's internal state to 2
.
- after that the number
0
(still pending in the trigger:out0
) is sent to sel:1
, setting it's internal state to 0
!!!
As you can see, at the end of #3 the internal state of [select]
is 0
, even though the last number generated by [random]
was 2
(because the left-most outlet of [trigger]
will only send to 0
after it has sent the 2
, due to stack-unrolling).
Solution
The solution is simple: make sure that the state of [select]
contains the last displayed value, rather than the last one generated on the stack. avoid feedback when modifying the internal state.
E.g (using local send/receive to for nicer ASCII-art)
[r $0-again]
|
[bang(
|
[random 3]
|
| [r $0-last]
| |
[select]
| |
| [t f f]
| | |
| | [s $0-last]
| |
| [print]
|
[s $0-again]