How to see in the post window the choices taken by a Prand || Newbie Question

Hi everyone,
I would like to see the names of the variables choosen randomly in the post window.
Is there a method to do that ?

(
var z, pseq1,pseq2,pseq3,pseq4,pseq5,pseq6,pseq7,pseq8,pseq9,pseq10,pseq11,pseq12,pseq13,pseq14;

// 14teen phrases
        pseq1 = Pseq([0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]);
        pseq2 = Pseq([0.9, 0.2, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]);
        pseq3 = Pseq([0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.2]);
        pseq4 = Pseq([0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.0, 0.7, 0.0, 0.0]);
        pseq5 = Pseq([0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.2, 0.7, 0.2, 0.0]);
        pseq6 = Pseq([0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.2, 0.2]);
        pseq7 = Pseq([0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0]);
        pseq8 = Pseq([0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0]);
        pseq9 = Pseq([0.9, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0]);
        pseq10 = Pseq([0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.4, 0.2, 0.4, 0.2]);
        pseq11 = Pseq([0.9, 0.0, 0.2, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0]);
        pseq12 = Pseq([0.9, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.7, 0.0, 0.0]);
        pseq13 = Pseq([0.9, 0.7, 0.7, 0.0, 0.0, 0.2, 0.2, 0.2, 0.0, 0.0]);
        pseq14 = Pseq([0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]);

z = Prand(list:[pseq1,pseq2,pseq3,pseq4,pseq5,pseq6,pseq7,pseq8,pseq9,pseq10,pseq11,pseq12,pseq13,pseq14],repeats: 10).nextN(10);

)

Thank you in advance like always.

Sorry if it is too silly.

Something like this:

(
// HOLY WALL OF NUMBERS
var sequences = [
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.2, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.2],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.2, 0.7, 0.2, 0.0],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.2, 0.2],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0],
    [0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.4, 0.2, 0.4, 0.2],
    [0.9, 0.0, 0.2, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.7, 0.7, 0.0, 0.0, 0.2, 0.2, 0.2, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
].collect{|list| Pseq(list)};

Pswitch1(
    sequences,
    Pwhite(0,sequences.size).trace
).trace.play
)
1 Like

Thank you very much @elgiano
Sorry, but probably I wasn’t clear.

I would like to see in the post window, if possible …
the names of the variables choosen by the Prand, like:

" It’s an example just to show what I mean … "
pseq1, pseq5, pseq6, pseq12, pseq14, pseq3, pseq7 etc…

I need it just to understand which part will be played, I mean which Pseq([]); will be played, in which order.

I thought that maybe to use .asString it could have worked, but it’s not the correct way …:

z = Prand(list:[pseq1,pseq2,pseq3,pseq4,pseq5,pseq6,pseq7,pseq8,pseq9,pseq10,pseq11,pseq12,pseq13,pseq14],repeats: 10); 
z.asString.nextN(10)

I probably didn’t understand the example well …
I can find a way in this direction with a case method (control structure)

(
// HOLY WALL OF NUMBERS
var sequences = [
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.2, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.2],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.2, 0.7, 0.2, 0.0],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.2, 0.2],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0],
    [0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.4, 0.2, 0.4, 0.2],
    [0.9, 0.0, 0.2, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.7, 0.7, 0.0, 0.0, 0.2, 0.2, 0.2, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
].collect{|list| Pseq(list)};

Pswitch1(
    sequences,
	//Prand((0..13),1).trace
	Prand((0..sequences.size),10).trace
).play
)

@elgiano: neat tracing trick, never noticed this option of playing without Pbind (or I have forgotten it) !

See the difference, trace causes timed post.

Pswitch([1, 2], Pwhite(0, 1)).play
Pswitch([1, 2], Pwhite(0, 1).trace).play

Pseq([1, 2]).play
Pseq([1, 2]).trace.play

@RandColors, you could decide how often you want to have the number printed. If it’s enough to see it one time, I’d take a Pn + Plazy construct:

(
~sequences = [
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.2, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.2],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.2, 0.2, 0.7, 0.2, 0.0],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.2, 0.2],
    [0.9, 0.2, 0.2, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.2, 0.2, 0.2, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0, 0.4, 0.0],
    [0.9, 0.0, 0.0, 0.4, 0.0, 0.0, 0.4, 0.2, 0.4, 0.2],
    [0.9, 0.0, 0.2, 0.7, 0.0, 0.2, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.7, 0.0, 0.0, 0.0, 0.7, 0.0, 0.0],
    [0.9, 0.7, 0.7, 0.0, 0.0, 0.2, 0.2, 0.2, 0.0, 0.0],
    [0.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
].collect { |list| Pseq(list) };

Pbind(
	\dur, 0.2,
	\midinote, Pn(Plazy {
		var i = (0..~sequences.size).choose.postln;
		Pswitch1(~sequences, i)
	} * 5 + 60)
).play
)
1 Like

… but actually even easier with Pswitch:

Pbind(
	\dur, 0.2,
	\midinote, Pswitch(~sequences, Prand((0..~sequences.size), inf).trace) * 5 + 60
).play
1 Like

@RandColors
Yeah, it was clear, sorry if I didn’t explain my code at all.
I don’t think it’s possible to show variable names: I don’t think Prand doesn’t even know about them, as they are probably translated by the interpreter to their content.
So, what my code does is:

  1. instead of “numbered” variable names, we use “row” numbers in a matrix. That is, instead of showing pseq1, we are going to show 0, which is the first row in matrix sequences
  2. I use Pwhite to choose a row from sequences. Then .trace is printing the row number. That is, it will post 0 when it chooses pseq1, 1 for pseq2 and so on.
  3. I didn’t understand that you wanted the whole Pseq, I assumed you wanted to poll the next value from a randomly chosen Pseq. This is why I used Pswitch1, that does exactly that, but you can also use Pswitch to get a whole Pseq and poll it until it ends, before choosing another one.

So, the integer numbers you saw in the post window were the info you wanted ( except that you can’t see variable names).
For everything else, I think we need to know more about what you actually want to do with this information :slight_smile:

1 Like

If you don’t want the index into the array posted, but some more explicit name, you can bind the sequences in an environment/event (with keys for more suggestive names) and trace just one key (the sequence’s name). Use e.g. Pdict to select instead then.

~seqdict = (seqAlpha: Pseq([1, 2, 3]), seqBeta: Pseq([5, 4, 3]), seqGamma: Pseq([6, 7, 6]))

// quick example, seq size assumed constant across the dict

(p = Pbind(
	\seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf)), 
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
))


5 do: { p.asStream.nextN(3, ()).postln }

p.trace(\seqname).play

If you really must have the seq name posted only once it changes

q = Prand(~seqdict.keys(Array), inf).trace;

(p = Pbind(
	\seqname, Pstutter(3, q), 
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
))

p.play

If you use a Pdef for q instead you can even turn the tracing on/off while p plays (by changing q’s source).

2 Likes

thank you all @elgiano, @dkmayer and @RFluff :love_you_gesture:
for this specific problem I think using a dictionary is the clearest thing.

Actually that glitches sound a bit on changes. It turns out that in this application @dkmayer’s PL is better “out of the box”.

~q = Prand(~seqdict.keys(Array), inf).trace;

(p = Pbind(
	\seqname, Pstutter(3, PL(\q)),
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
).play)

~q = Prand(~seqdict.keys(Array), inf); // no trace

(The issue with Pdef seems to be that it doesn’t do the replacement “on the bar” by default, so it will send two overlapping notes on source changes.)

Actually that was a rather silly mistake on my behalf; if using Pdefn (not Pdef) or PatternProxy directly (and not EventPatternProxy) here, replacement works properly with the JITlib proxy machinery too. E.g.,

q = PatternProxy(Prand(~seqdict.keys(Array), inf).trace);

(p = Pbind(
	\seqname, Pstutter(3, q),
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
).play)

q.source = Prand(~seqdict.keys(Array), inf);

If you’re curious, the “glitchy” version:

Pdef(\setSeqName, Pbind(\seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf))))

(Pdef(\top, Pbind(
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
) <> Pdef(\setSeqName)).play)

Pdef(\setSeqName, Pbind(\seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf).trace)))

Can be made not so with Pbindef, while sticking with the Pdef namespace. There’s still a “glitch” when a Pbindef is used for the first time to replace a Pdef(Pbind) but not in subsequent changes between Pbindefs.

Pbindef(\setSeqName, \seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf)).trace)
Pbindef(\setSeqName, \seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf).trace))
Pbindef(\setSeqName, \seqname, Pstutter(3, Prand(~seqdict.keys(Array), inf)))

Since we are here, now talking about dictionaries: aren’t Pdict and Psym almost identical?
I actually didn’t know about Pdict (because Psym is in the Pattern Guide and Pdict is not if I’m not wrong), and then since @RFluff mentioned it I looked at its source… they seem to be the same thing to me … except that Psym looks into Pdef if no dict is provided, and can parallelise if the keys pattern returns arrays of keys.

Except for the swapped order of augments (even though they’re both from JITlib :frowning:) they are indeed equivalent here.

q = Prand(~seqdict.keys(Array), inf).trace;

(p = Pbind(
	\seqname, Pstutter(3, q),
	\degree, Pnsym(Pkey(\seqname), ~seqdict), // vs
	\degree, Pdict(~seqdict, Pkey(\seqname)),
	\dur, 0.2
).play)

Pnsym is a slightly nicer (less typing) if you want to store the patterns in Pdefn’s, although sometimes that’s not what you want…

On the other hand, Pdict has other bells and whistles of its own like a repeat arg and a 4th default value arg. It’s not terribly clear to me where the default values come from in Pnsym…

Pnsym(\foo, (foo: 22)).asStream.next // -> 22
Pnsym(\nope, (foo: 22)).asStream.next // -> 1 (oddly)
Pdict((foo: 22), \nope).asStream.next // -> nil

It turns out Psym/Pnsym does

	lookUp { arg key;
		^(dict ?? { this.lookupClass.all }).at(key.asSymbol) ?? { this.lookupClass.default }
	}

So even if you pass your own dict to it, it will replace anything not found with Pdef.default or Pdefn.default.

Pdef.default // -> a Pn
Pdefn.default // -> 1

So that behavior can be pretty confusing if you’re using your own separate dict for Psym/Pnsym… Also the lookupClass is hardcoded as a method for both of these, so something like

Pnsym(\nope, (foo: 22)).lookupClass_((default: 42)) // err

doesn’t work. So you’d have subclass Psym for a more useful variant with their non-default dictionary. (You could also do a custom Dictionary subclass with a way to set default lookups per dict, i.e. things which fail otherwise. I don’t think there is one like that in the classlib.)

Pdict is older. Quite likely Julian changed his mind about how this should be implemented and didn’t want to break code by removing the older one.

For that matter, there is one way in which the interfaces could be seen as consistent: in Pdict, the emphasis in the class name is on the dictionary and the dictionary is the first argument. In Psym, the class name emphasizes the symbol pattern, and the symbol pattern is the first argument. So it’s inconsistent from the computer science perspective of interface descriptors but more consistent from the perspective of human semantics.

hjh

Since the dictionary arg is optional in Psym/Pnsym, it makes sense for the key to be first for those. On the other hand, Pdict is consistent with the order of arguments of Pindex.new(listPat, indexPat and Pswitch.new(list, which: 0) (If someone wants to ask how those two differ, let’s make a different thread…)