«Converting an environment in a prototype object» by julian.rohrhuber
on 11 Jul'21 15:11 in/* I often like to write out a library as an environment, like:
~start_sound = { |freq, amp| <...> }; ~start_high_pitch_sound = { |amp| ~start_sound.(14000, amp) };
… and then use loadRelative to load that library.
This, however has the problem that you can't stick the whole library into an environment that you call from the outside. e.g.
q = (); q.use { resolveRelative("/library.scd") };
and then trying:
q.start_sound(700, 0.1); q.start_high_pitch_sound(0.1);
will not work. Firstly, it will expect the environment as first argument of each function, second, it won't find a function like ~start_sound from within the call context.
Here is a way to convert an environment as needed.
*/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
~constructPseudoMethods = { |envir|
var newEnvir = envir.collect { |value|
var argNames, argBlock, namesBlock, code, func;
if(value.isKindOf(Function)) {
func = value;
argNames = func.def.argumentString(withDefaultValues: true);
namesBlock = func.def.argumentString(withDefaultValues: false);
argBlock = if(argNames.notNil) { "|self, " ++ argNames ++ "|" };
code = "{ |func, envir| { % envir.use { func.value(%) } } }".format(argBlock ? "", namesBlock ? "");
//code.postln;
code.interpret.value(func, envir)
} {
value
}
};
newEnvir.know = true; // we want a prototype object style environment
};
reception
Note that this doesn't yet work with ellipsis arguments.