Pseq with side effects; why different behavior in asStream vs play?

Compare

r = Pseq([p{|e| e[\dur]=0.3; e.yield}, p{|e| e.postln.yield}, nil]).asStream;
e = ()
r.next(e); // -> ( 'dur': 0.3 )
r.next(e); // -> ( 'dur': 0.3 ) and posts it

With

Pseq([p{|e| e[\dur]=0.3; e.yield}, p{|e| e.postln.yield}, nil]).play; // posts (  )

This 2nd snippet posts ( ), and the 2nd event played has dur of 1.

I totally understand why the first snippet of code behaves like it does, i.e. Pseq actually passes the same inevent from one sequenced sub-stream to the next, so side-effects propage to siblings (Pseq-wise)

				list.size.do({ arg i;
					item = list.wrapAt(i + offsetValue);
					inval = item.embedInStream(inval);
				});

What I don’t understand is why playing a Pseq has a different behavior which doesn’t propagate side effects. Any ideas?

Actually the answer was fairly predictable; EventStreamPlayer does:

	prNext { arg inTime;
		var nextTime;
		var outEvent = stream.next(event.copy);

I.e. it will create a new copy of the inevent for every “pull”, so the EventStreamPlayer code is equivalent with doing

r.next(());
r.next(());

in the first snippet.

Patterns are not quite meant to be used in the manner of your first example here. They can be, but at your own risk, and there’s never any guarantee that other parts of the class library will cascade event changes like that.

Typical use is to pass an “empty” event prototype in, every time, so that the patterns’ modifications to the prototype are isolated from any other next invocation (as EventStreamPlayer does) – a variation on the idea of encapsulation.

hjh

1 Like