return when desugaring to closures

Lex Spoon spoon at google.com
Tue Sep 2 14:16:13 PDT 2008


On Sun, Aug 24, 2008 at 3:17 AM, Brendan Eich <brendan at mozilla.org> wrote:
> First, let's settle the hash over whether any desugaring without
> extensions such as return-to-label, reformed lexical scope, tamed
> this, banished arguments, etc. etc., trumps adding a new binding
> form, to wit: let as block scoped var.

With no extensions, it is true, return would end up returning from a
different method under the proposed rewrite.  Likewise, this and
arguments would cause trouble.  Possibly break and continue would,
depending on what their precise semantics are.

However, they work under some specific extensions that appear to
benefit JavaScript anyway.  I suspect that most languages with both
return expressions and nested functions will eventually want a way to
return from other than the innermost function.  More generally, it
would be really nice if programmers could safely add a nested function
without losing access to important things from their surrounding
scope.  That goes not just for return, but also arguments, this,
break, and continue.  It's an orthoganality problem.  With
JavaScript's current limited return expression, programmers have
trouble when they try to use both function nesting and return at the
same time.  Using one feature makes it harder to use the other.

That's a philosophical argument, and so people will disagree.  That's
why I tried to pull in experience with existing languages that have
both of these features.  Not all that many do, actually.  The
languages that push nested functions the hardest are functional
languages, and most of them do not have return.  Of those that have
both, though, it's notable that most also have non-local return.  I
earlier listed Scala, Smalltalk, and Lisp as examples.  On the flip
side, I can only think of two languages: Java (counting anonymous
inner classes as nested functions) and X10 (which is based closely on
Java).  Can anyone else think of other language experiences to compare
against?

Looking at this experience, it's fair to say that non-local return
works out fine in practice.  Further, the two languages in my list do
not have this feature, also make it annoying to write nested functions
that also want to return.  I guess it's a matter of taste, but I have
to say that Java (and X10), despite their many other advantages, don't
make it concise nor elegant to nest anonymous classes very much.
Java's designers seem to agree, having written their collections
library not to support a style where you'd use a lot of nested
anonymous classes.

Stepping back, let me emphasize that I'm not religious about
desugaring as a definition approach.  I'm more concerned that an
intuitive-looking rewrite doesn't work.  Programmers are going to do
intuitive-seeming things to their code, and it's a nicer language when
those intuitive-seeming things are in fact safe.  Of course, if it
can't be done, it can't be done, and the wart has to stay.  In this
case, though, the wart can be removed by adding a feature that has
merits of its own.

Thus, I don't know what the Harmony process is, but I would recommend
a careful look at accessing "return", "this", and "arguments" for
functions surrounding the immediately enclosing function.  If those
work out as well as they appear to, then programmers would have one
less thing to worry about when they introduce nested functions into
their programs.

Finally, there was a little bit of question about what the semantics
would be.  Let me go into just a little more detail.  The idea is that
instead of just "return foo", you could also put a label on the
return.  I don't know what the syntax would be, but as a straw man,
maybe it would be "return:bar foo".  This notation means to return
"foo" from the function named "bar".  If "bar" happens to be the
immediately enclosing function, then you return exactly as in
JavaScript right now.  Otherwise, you pop stack frames until you get
to the correct "bar" stack frame.  You then return from that one.  If
that frame has already popped, then the return fails, much like an
exception that is never handled.  Does that explain it well enough, or
should I go on?

-Lex


More information about the Es-discuss mailing list