What explains that Pkey can "figure out" how to respond to asStream depending on repeats in constructor

This is probably easy enough to explain but

Pkey(\foo, 1).asStream // -> a Routine
Pkey(\foo).asStream // -> a FuncStream

it’s not obvious how that “magic” happens just from Pkey’s source code:

Pkey : Pattern {
	var	<>key, <>repeats;

	*new { |key, repeats|
		^super.newCopyArgs(key, repeats)
	}

	storeArgs { ^[key, repeats] }

	asStream {
		var	keystream = key.asStream;
		// avoid creating a routine
		var stream = FuncStream({ |inevent| inevent !? { inevent[keystream.next(inevent)] } });
		^if(repeats.isNil) { stream } { stream.fin(repeats) }
	}

	embedInStream { |inval|
		var outval, keystream = key.asStream;
		(repeats.value(inval) ?? { inf }).do {
			outval = inval[keystream.next(inval)];
			if(outval.isNil) { ^inval };
			inval = outval.yield;
		};
		^inval
	}
}

I mean

Pkey(\foo).asStream // -> a FuncStream

is obvious because there’s an implementation in Pkey that does that special handling. But how comes Pkey(\foo, 1).asStream still returns a Routine?

N.B. you actually need the 2nd form in some cases, in particular within Pseqs

r = (Pbind(\bar, Pseq([Pkey(\foo) + 1, 22])) <> (foo: 3)).asStream
r.nextN(3, ()) // never gets to 22

// fixy
r = (Pbind(\bar, Pseq([Pkey(\foo, 1) + 1, 22])) <> (foo: 3)).asStream

Duh, I missed that stream = FuncStream is not retuned unconditionally in asStream

		^if(repeats.isNil) { stream } { stream.fin(repeats) }

fin is a somewhat obscure method in Object (as least I haven’t seen/used it so far) being called here

	fin { arg n = 1;
		^r {|inval|
			var item;
			n.do {
				item = this.next(inval);
				if (item.isNil) { nil.alwaysYield };
				inval = item.yield
			}
		}
	}

(In fact this call in Pkey is the only use for fin in classlib, as least searched with the regex .fin[^a-z]. )

It’s basically the Object/stream counterpart of Pfin; Pattern overrides fin to return a Pfin.

^if(repeats.isNil) { stream } { stream.fin(repeats) }

The only way to .fin a stream is with a routine.

Crossed messages… We were writing at the same time.

hjh

1 Like