Evaluating a Function and Returning a Keyed Result

I have a small question about how to code something in SuperCollider.
Let’s say I have a very simple function like so

~threeParts = {|number|
	var n1=number*2, n2=number*3, n3=number*4;
	[n1, n2, n3];
}

I’d like to be able to enter a number and specifically request a return from a key named “first”, “second”, or “third” - rather than returning an array of [n1, n2, n3] and then using indexing accordingly.

Something like:

~threeParts.(first: 10);

Is there any way to do this?

Use an event.

f = { 
   ... Blah blah blah
   ( \first : x, \second: y)
}

Then…

f.(10).first

Just a dumb thing to mention for anyone who finds this post later, with a similar problem:
“first” might not be a great name for your key :slight_smile:

In general, it’s easier to compose smaller operations into larger, rather than decomposing a complex function into the components.

~first = { |number| number * 2 };
~second = { |number| number * 3 };
~third = { |number| number * 4 };

~threeParts = { |number|
	[~first.(number), ~second.(number), ~third.(number)]
};

… and when you do it this way, then the simplest way to select the desired result based on a symbolic key is simply to use the corresponding environment variable:

~first.(10);

So in some ways, the problem as stated is asking for a different way to select something based on a name, when there are already good ways that are more efficient or idiomatic. Sometimes we get stuck on an idea and think “I have to do it this way,” while overlooking simpler ways.

(One might argue that ~first, ~second, ~third are duplicating code. In this specific case, the duplicated code [the argument name] couldn’t be factored out into another function – but if it’s a complex function with some shared operations between the three, then those could be factored out. In the above case, you could also just parameterize: { |number, mul| number * mul }.)

hjh