I’m going to take a step back and describe the execution flow of a pattern’s stream.
- You call
.next
.
- The stream resumes from the last point where it yielded a value.
- Now the stream does some processing that is relevant to the next value to be returned.
- It returns (
.yield
s) the value, and pauses to wait for the next .next
call.
- Back to 1.
At 3, patterns usually don’t look into the future. That is, the processing is for the one, single next value that will be returned.
The flow you’re trying to achieve is:
- You call
.next
.
- The stream resumes from the last point where it yielded a value.
- If a flag had been set previously: either end, or otherwise modify the behavior.
- Processing that is relevant to the next value to be returned.
-
And the stream (upon a flag) sets up some future state that will affect what happens after the next
.next
call.
-
.yield
, and wait for the next .next
call.
The point is that the logic in 3 and 5 doesn’t exist in most patterns.
So the conclusion is that it’s probably not helpful to formulate the question in terms of “how to have the Plazy executed only when another pattern (a Pseq) trips a Ref.” This is going to make the logic more complicated and easier to break.
The second thing is that Plazy does not evaluate the function for every .next
.
(
Pn(
Plazy {
"evaluating Plazy now".postln;
Pseq(Array.fill(3, { rrand(1, 3) }), 2)
},
inf
).trace.asStream.nextN(10)
)
evaluating Plazy now
3
3
1
3
3
1
evaluating Plazy now
1
3
3
1
-> [ 3, 3, 1, 3, 3, 1, 1, 3, 3, 1 ]
Here, Plazy produces a Pseq with a 3-item array, repeated twice – and indeed, you get six values before Plazy runs again.
So there isn’t a direct way to force Plazy to reset based on a flag from somewhere else. When the stream is in the middle of a pattern returned by Plazy, then Plazy has no control.
I’m not entirely clear what you’re trying to do, but I have a feeling that “disposable Pbind” might be a better approach. That is, many pattern examples put Pbind at the top, so then you might think that Pbind should always be at the top, and any other flow of control should be shoehorned into that. This is often too complicated, and expressed more directly by using a Pbind for one phrase.
What about…?
(
b = {
var array = Array.fill(rrand(3, 10), { rrand(0.2, 0.8) });
array.putLast(Ref(array.last));
Pseq(array)
};
p = Pn(
Pbind(
// note, 'b' is finite --
// when the Pseq ends, it will stop the whole Pbind
\dur, Plazy { b.value },
\degree, Pseries(0, 1, inf),
// change something based on "last item"
// note that this is a SEPARATE requirement from
// the flow of control
// this one can *only* be handled by marking the last value
// the pattern reset can NOT be handled by marking the last value
\octave, Pif(Pfunc { |ev| ev[\dur].isKindOf(Ref) }, 6, 5),
// finally, make sure the 'dur' Ref doesn't break
\dur, Pfunc { |ev| ev[\dur].dereference }
),
inf
).play;
)
hjh