Function with Global Variable

Hi all-
Running into a little confusion here, I was hoping someone could help.

I’ve created a function to take a “starting number”. If the starting number drops below 2, it is reassigned a value of 20. There is also a random function, depending on the outcome it will subtract either a 1 or a 2 from the starting number, with each iteration.

~func ={ |start|
	var rand = 3.rand;
	start.postln;
	if (start<2, {start = 20;},
		{
	case
	{rand == 0} {start = start - 1;}
	{rand == 1} {start;}
	{rand == 2} {start - 2;};
	});
	start;
};

Now, obviously, if I start calling on this function with a start number, it never accumulates the changes.

~func.(10);

I could change all of the variables in ~func, so that they were global variables - and that would potentially fix the issue… but then, the function would no longer be flexible to be used in multiple instances.

I’m curious how a problem like this is dealt with in SuperCollider. My apologies if I haven’t explained it well. I can try to fill in some of the details as necessary.

Thank you!

Hi,

It looks like you want to make a function that you can call many times and get a different value out? That isn’t best achieved with a function, but with a routine (or something else).

Does this do what you want?

~mkRoutine =  { |initialValue|
	fork {
		var start = initialValue;
		loop {
			if(start < 2) { 
				start = 20;
			} {
				var r = 3.rand;
				case 
				{r == 0 } { start = start - 1 }
				{r == 2 } { start = start - 2 }
			};
			
			start.yield;
		}
	}
}
~f = ~mkRoutine.(20);

// repeatedly call this
~f.()

Which produces this output?

-> 18
-> 16
-> 15
-> 13
-> 11
-> 10
-> 9
-> 7
-> 7
-> 7
-> 7
-> 6
-> 5
-> 5
-> 5
-> 5
-> 5
-> 5
-> 3
-> 3
-> 1
-> 20
-> 20
1 Like

Well, I was hoping to use it as a function, since I’m using it with the Pattern language… but there is maybe an easy way to wrap it into a Prout, so I will dig around and see what I can come up with. Thanks!

Just remove the fork and put it directly in the Prout as a function.

~mkRoutine =  { |initialValue|
	var start = initialValue;
	loop {
		if(start < 2) { 
			start = 20;
		} {
			var r = 3.rand;
			case 
			{r == 0 } { start = start - 1 }
			{r == 2 } { start = start - 2 }
		};
		
		start.yield;
	}
};

Pbind(\dur, 1, \f, Prout{ ~mkRoutine.(10) }, ).trace.play
1 Like

It’s about as easy as it could possibly be: Prout { ... }.

hjh

And in case you do ever want a simple closure, the idiom is:

var f = { var x = 0; { x = x + 1; x } };
var g = f.value; 
[g.value, g.value]
1 Like

Out of curiosity, if I were dealing with an array in this situation, as opposed to a single number - would there be a way to take the array returned by Prout and apply it to something like a Prand?