Return statement

Hey guys,
I’m trying to understand how to replicate in SuperCollider a return/break mechanism like I am used in C++ and other programming languages.

In practice I’m trying to replicate this snippet of code (very basic for the sake of semplicity and just to stimulate the conversation):

int lookfor(int p)
{
  for(int i=0; i<number_of_checks; i++)
    if( p == check_array[i] ) return(1);
  return(0);
}

I was able to use the block method on a function to create something I think is pretty similar.
Here’s the code of the function and also some code test:

~check_array = [7,8,9];
(
~func_lookfor = {
	|p|
	var return_value = 0;
	return_value = block {
		|break|
		for( 0, ~check_array.size, {
			|i|
			if( p == ~check_array[i], { 
				"hey, found, bye!".postln;
				break.value(1); 
			});
		});
	};
	return_value;
};
)
~func_lookfor.value(8);

I’m wondering if there’s a better way to implement this kind of behaviour.

Posting this also for personal reference because in the past I posted a similar question (link).

Thank you for you support, as always.

There many alternative ways to implement this that do not require for loops or break statements, e.g.

(
Set[1,2,3,4,5].includes(3).debug("3 in set? ");
Set[1,2,3,4,5].includes(8).debug("8 in set? ")
)
1 Like

Methods in a class definition can early-return using ^. (This is how includes does it.)

Functions have no equivalent of return from C/Java. So the first example in this thread is impossible to translate as a function token-for-token into SC (though it could be translated as a method).

block on a function is more like break in C. In a function, the closest you can get to early-return is to early-exit from an inner block.

Your block example doesn’t really need the variable, though – you could write it a little more tightly like this. Also for isn’t really idiomatic SuperCollider – we aren’t limited to C’s archaic control structures :laughing:

~check_array = [7,8,9];
(
~func_lookfor = {
	|p|
	block { |break|
		~check_array.do { |item|
			if( p == item ) { 
				"hey, found, bye!".postln;
				break.value(1); 
			};
		};
		0
	};
};
)
~func_lookfor.value(8);

I can think of one more way to simulate an early exit from a loop, though I can’t say this is “better” than block: yield. The Routine pauses at the exit point and then, instead of asking it to continue, you just discard it.

~check_array = [7,8,9];
(
~func_lookfor = {
	|p|
	Routine({
		~check_array.do { |item|
			if( p == item ) { 
				"hey, found, bye!".postln;
				1.yield;
			};
		};
		0.yield;  // yield is required here
	}).next
};
)
~func_lookfor.value(8);

hjh

1 Like