javascript - On a one-time self-re-defining function pattern -
consider following pattern:
function foo /* aka outer_foo */ () { // === stage 1 === // declaration , initialization of closure variables var ... <closure_vars> ...; // initialization of closure_vars // (possibly expensive and/or depending on values known @ run-time) // === stage 2 === // one-time redefinition of foo foo = function /* inner_foo */ ( arg0, ... ) { var results; // code computing value of results based on closure_vars, arg0, ... // foo never modified here return results; }; // === stage 3 === // invocation of inner function , returning of result return foo.apply( this, arguments ); }
for convenience, use terms outer_foo , inner_foo designate, respectively, outer , inner functions above, though code not use these identifiers.
the body of outer_foo comprises 3 stages (the last 2 consisting of single statement each):
- declaration , initialization of closure variables;
- redefinition of identifier
foo
; - passing inner_foo arguments passed outer_foo, , returning result.
the body of outer_foo executed @ once, namely, first time "the function named foo
" called, if ever happens. henceforth, body of outer_foo unreachable, , subsequent calls "the function named foo
" result in execution of inner_foo.
in general, 1 may envision variations on pattern 1, essential constraints on basic scheme i'm talking here are:
foo
re-defined once during execution ofouter_foo
2;foo
never re-defined during execution ofinner_foo
.
(if these essential constraints violated, bets off; such case outside scope of question.)
i aware of @ least 1 downside of scheme: practitioners consider self-redefining functions confusing, detrimental code readability, and/or inherently in poor taste, when re-definition happens once in deterministic manner, case in scheme above.
my question is:
does scheme have additional downsides, , if so, they?
i'm particularly interested in downsides specific javascript.
1 example,
function foo /* aka outer_foo */ () { var inner_foo, ... <closure_vars> ...; if ( some_deterministic_test() ) { inner_foo = function ( arg0, ... ) { // etc. } } else { inner_foo = function ( arg0, ... ) { // etc. } } foo = inner_foo; return foo.apply( this, arguments ); }
in variant, function assigned foo
depends on test performed @ run-time.
2 here it's tempting stipulate foo
not must re-defined once within outer_foo, done "deterministically". of course, deviation "determinism" (however 1 chooses define it) in final setting of foo
can increase complexity of code's run-time behavior. unfortunately, don't know how make stipulation precise without descending maze of lawyerly minutiae. best add weasely—and borderline incoherent—phrase "the more deterministic better", , hope readers point. utility of additional stipulation, however, rule out perverse, wholly unrealistic, scenarios (e.g. having final value of foo
depend on outcome of random process), left out.
i can think of 2 additional points should aware of:
- performance. compilers people mentioned. of them confused pattern, , might not able optimise if different pattern used. might or might not concern, should make sure test it.
- broken contracts. expect outer_foo executed @ once. might not case! might pass around , put reference somewhere, not become unreachable when being called. sure, that's unlikely, depending on requirements might want guard against it.
after all, it's kind of broken design, mere alias (var f = foo; f()
) should never alter functionality. make sure consumers/users know doing don't trip on it.
Comments
Post a Comment