Newbie question about multiple args in a Routine, how it works?

Hello everyne,
I can’t understand what is the correct way to write it.

(
~r = Routine({|inval, ciclo =6,nTimes = 1,metro = 4,bpm = 120|

	var dur = (60/bpm)*metro*1/8;
	var c;
	inval.postln;

	(ciclo*nTimes).do({|i|

		c = [255,0,0,0,0,0].rotate(i%ciclo).postln;

		~n1.sendMsg('/test',c[0],c[1],c[2],c[3],c[4],c[5]);
		dur.yield;
		~n1.sendMsg('/test',0,0,0,0,0,0); // turn all OFF
	})

}).reset.play();
)

~r.value("hello routine",6,1,4,120).reset.play();
  1. Why it doesn’t work, I just want to pass the arguments…?
  2. Why I need “inval” to avoid errors ?
  3. How to pass Array like arguments eg. I would love to change c = [255,0,0,0,0,0]

Thanks in advance

1 & 2. Routine:-value only passes a single argument, but you can pass the arguments you need as an array and unpack them inside the Routine’s function:

(
~r = Routine({|args|
	var x, y;
	#x, y = args; // equivalent to `x = args[0]; y = args[1];`
	"x is %, y is %\n".postf(x, y);
});

~r.value([1, 2]);
)
  1. I’m not sure this is what you are asking, but there is nothing stopping you from passing an array:
(
~r = Routine({|args|
	var x, y;
	#x, y = args;
	"x is %, y is %\n".postf(x, y);
});

~r.value([1, [1, 2, 3]]);
)
2 Likes

The other thing I noticed here is some confusion about how to “run” the routine.

If you .play the routine, then it’s scheduled on a clock. At the scheduled time, the clock calls next on the routine. In that case, you don’t have any control over what is passed in – the clock does it (and it passes in the time of waking up).

So, if you want to pass specific data into the routine, you should not play it – but the example does play it (and dur.yield suggests that playing was always the intention).

If the routine is being played on a clock, then you should not .value it separately.

It looks like the arguments are intended to set values that will be used for the entire duration of the routine. So, a better approach is to write a function that returns a Routine, with those values applied:

(
~r = { |ciclo = 6, nTimes = 1, metro = 4, bpm = 120, c|
	var dur = (60 / bpm) * metro / 8;
	// this Routine is the function's return object
	Routine {
		(ciclo * nTimes).do { |i|
			var array = c.rotate(i % ciclo).postln;
			~n1.sendMsg(*(['/test'] ++ array));
			dur.yield;
			~n1.sendMsg(*(['/test'] ++ [0, 0, 0, 0, 0, 0])); // turn all OFF
		};
	};
};

~theRoutine = ~r.value(... arguments...);
~theRoutine.play;
)

hjh

3 Likes

Thank you very much guys!
Finally it’s clear.