Thunk with arguments?
[email protected] Sat, 23 May 2020 09:25:22 +0800
| Newsgroups | gmane.comp.audio.supercollider.devel |
|---|---|
| Message-ID | <CAFniQ7WHS9y-3+c__Nvz1jvkvbUrma6APwDjQED3Z94ro7TPUw@mail.gmail.com> |
Hi,
Would there be any objection to adding arguments to Thunk, as below?
Rationale: rfluff on scsynth.org aka eleses on github identified bugs
where patterns' cleanup functions might evaluate twice. It's very
thorny to try to fix it so that cleanup functions are never
double-evaluated, and IIRC the closest he got to a complete solution
involved some surgery on patterns' usage of EventStreamCleanup -- so
there is some risk in fixing the logic.
The other approach is to wrap the cleanup functions in something that
will evaluate once and once only. Thunk does that.
But PmonoArtic uses a Boolean flag passed into the cleanup function.
Thunk, in its current form, doesn't support function arguments (and,
in a comment, says that it shouldn't).
If we change Thunk to allow arguments, then all of the double-cleanup
bugs go away simply by adding `function = Thunk(function);` in two
places in EventStreamCleanup
(https://scsynth.org/t/generalized-conceptual-design-flaw-double-free-of-cleanups/1843/18
: "There are no failures with the Thunk addition alone (no need to
change Pchain)").
It would be a breaking change:
t = Thunk { |a| if(a.isNil) { rrand(1, 10).squared } { a.squared } };
t.value(11);
Currently, this would return a square integer 1 to 100. With the
proposed change, it would return 121 (and any subsequent evaluation,
with any argument, would still return 121).
If it's important that Thunk not allow arguments, then I'd propose
adding an IdempotentFunction that does allow them.
hjh
Thunk : AbstractFunction {
// a thunk is an unevaluated value.
// it gets evaluated once and then always returns that value.
// also known as a "promise" in Scheme.
var function, value;
*new { arg function;
^super.newCopyArgs(function)
}
value { |... args| ^this.prEvaluate(\valueArray, args) }
valueArray { |... args| ^this.prEvaluate(\valueArray, *args) }
valueEnvir { |... args| ^this.prEvaluate(\valueArrayEnvir, args) }
valueArrayEnvir { |... args| ^this.prEvaluate(\valueArrayEnvir, *args) }
prEvaluate { |selector, args|
^value ?? {
value = function.performList(selector, args);
function = nil;
value
}
}
}
_______________________________________________
sc-dev mailing list
info (subscription, etc.): http://www.birmingham.ac.uk/facilities/ea-studios/research/supercollider/mailinglist.aspx
archive: http://www.listarc.bham.ac.uk/marchives/sc-dev/
search: http://www.listarc.bham.ac.uk/lists/sc-dev/search/