reichsteinatwork at gmail.com
Mon Jun 27 04:49:47 PDT 2011
On Sat, 25 Jun 2011 05:50:05 +0200, Brendan Eich <brendan at mozilla.com>
> Let's get back to the problems with JS functions:
> 3. Tennent's principle of abstraction violations other than 'this'.
Why is this a *problem*?
I see having fully general non-local returns as a bigger problem than not
If you can declare a function inside another, let the inner function
escape and survive the outer, and is then allowed to try to return from
the outer function again ... that's simply bad. Just throwing an exception
seems a meek response to a fatal logical flaw.
Closures capture the variable environment of their point of declaration.
That's possible because the environment chain (if not the content of it)
is actually statically defined at the time the function closure is
created. It will keep making sense, no matter what happens later.
The stack frames/program counter/other dynamic behavior cannot be
meaningfully captured in the same way. It's not guaranteed to be the same
when the inner function is eventually called, or to even exist any more.
It's possible to define the language in such a way that this would make
sense, by snapshotting the dynamic state, but that would effectively
introduce call/cc, which seems like a overdoing it.
Exceptions work because they are defined in terms of the dynamic control
flow, not syntactic inclusion. Making a non-local return from an inner
function is just as senseless as expecting a syntactically containing
try/catch to catch a thrown exception.
The usecase generally used for non-local returns are user-implemented
control flow operators. This use would typically require only down-calls,
where all calls to the closure are performed inside the same invocation of
the calling function.
That's actually just a hack for emulating real call-by-name (which is what
best corresponds to the behavior of the built-in
control from operators like "for" and "while"). But even that can be
foiled, if you can capture a call-by-name argument
in a closure.
The current abstraction: function, function call and return, works so well
because it does what it does well - abstract
a statement with a single entry and a single exit (excepting exceptions
ofcourse :), which means that it can be used
wherever a statement can be used. Or an expression, if it returns a value.
It's a clean abstraction.
Adding non-local control-flow to a function allows it to have more than
one exit. It means that expressions can now
break or continue a loop, or return from the local function, where before
only statements could.
I think this got more confusing than I had hoped it would.
I guess the summary would be: I don't think Tennent's principle of
abstraction can be meaningfully applied to control flow when your
abstraction can survive the control flow that created it.
/L 'but "this" is a problem that is fixable'
Lasse Reichstein - reichsteinatwork at gmail.com
More information about the es-discuss