«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.