Brendan Eich brendan at mozilla.org
Thu Aug 21 15:07:25 PDT 2008

On Aug 21, 2008, at 1:33 PM, Peter Michaux wrote:

>> We've been over this. What if you replace print(y) with return y?
> Then we can do the following
> z = let (x = 2, y = x) {
>   return y;
> }

Anyone who knows JS sees return and looks for the nearest enclosing  
function form. Breaking this cognitive model looks like a mistake,  
therefore the let proposal for ES4 and the implementation in JS1.7 do  
not change the meaning of return.

Different semantics should have distinct syntax; similarity or  
symmetry may motivate reuse of syntactic forms or ideas. Here, there  
is no function to return y from, to be assigned to z. You could say  
"let desugars", but it doesn't say what it means.

> which is handy in a language that constantly deals with side effects.
> There is no Scheme "begin" or Lisp "progn" expression being proposed
> which means we will have to write the following pattern
> var y;
> let (x = 34) {
>   // side effects lines
>   document.getElementById('foo').className="n"+x;
>   // "return" y
>   y = x+4;
> }

Indeed, this looks like a case where an immediately applied function  
expression is the right tool.

> where it would be nice to write something like
> var y = let (x = 34) begin {
>   document.getElementById('foo').className="n"+x;
>   x+4;
> }
> or as suggested by the desugaring above
> var y = let (x = 34) {
>   document.getElementById('foo').className="n"+x;
>   return x+4;
> }

I wish I have flouted Netscape management's "make it look like Java"  
directive a bit harder, and reverted to BCPL from C as the ancestor:  
everything's an expression. But that ship has sailed.

On es-discuss we've had some proposals for new syntax to abruptly  
complete evaluation of an expression with its result, and to  
"expression-ize" statements. But these have not found much favor.

You can't go home again, truly.

> ) Functions are well understood
> quantities. Making functions as strong/useful as possible (e.g. adding
> tail call elimination) and then adding some sugar to existing common
> patterns (i.e. like having some built-in macros to ease boilerplate
> pain) makes a lot of sense to me. High quality functions and sugar
> built on them is a safe bet/insurance policy.

This all sounds great, but in order to reform functions, to recover  
their Schemeish better form, we need incompatible changes. A strict  
mode or similar is a big hammer, which does not compose as well as  
one would like. The greater its distance from the standard mode, the  
higher the migration tax. New syntax could do the trick, and indeed  
classes as sugar are viewed by the committee as appropriate syntax  
for higher-integrity constructor functions.

"Functions are well understood", but all of us had to remind  
ourselves (and one another, apparently :-/) of the problem children:  
arguments, this, var, function in block extensions, etc.

Anyway, the point at issue here concerns the other let forms, let  
blocks and let expressions, and whether they ought to be other ways  
of writing immediately applied function expressions. You don't gain  
safety, or insure against mistakes, just by desugaring this way. You  
have to address the usability or cognitive problems of return, etc.,  
changing where control flow goes. You have to do something beyond the  
desugaring to make arguments, this, etc. work

> "this" has been mentioned in other posts but it is "fixed" with the
> proposal that inner functions have their outer function's this value.

No, it's not. That proposal was backward-incompatible, and AFAIK not  
on the table for Harmony or in ES3.1. The most being done there,  
again if my memory serves, is for strict mode to pass undefined for  
this instead of null, which then would be replaced by the global object.

BTW, there are use-cases for break and continue in let blocks, which  
you break simply to provide another way to write function  
expressions, immediately applied. That does violence for no necessary  

>>> The reasons for these particular desugarings is this is exactly what
>>> JavaScript programmers are writing today.
>> So what?
> Maybe "so what?" but it makes it easy to explain what let is: simple
> sugar for an existing pattern.

The pattern doesn't need sugar, or in this case, vinegar that  
confuses where return goes, what |this| means, etc.

>> Programmers do what they must in a language that has not evolved in
>> nine years.
> True but by the same token as some of your arguments, that doesn't
> make current practices wrong either.

I never said it did. I'm saying your proposal to reinvent functions  
using let syntax is wrong, however. :-|

>> I cited Stockholm Syndrome the other day. It's a problem in JS- 
>> land. Users
>> happy with closures for everything should go on using them. These  
>> are not
>> the self-appointed victims I mean. But to say that let and block  
>> scope (and
>> possibly other binding facilities not desugarable to ES1-3.x) must be
>> spelled out exactly this way is bogus.
> I'm not suggesting the "must be" but that it seems sensible that  
> they are.

I don't know how to define "sensible".

Desugaring is a good exercise to avoid growing runtime semantics in  
the spec or any language model without needing to.

OTOH, if you can't say something new with old syntax, where it's  
important to be able to say something new (e.g., lexical scope only  
here down; generate a new name not equal to any string for use  
accessing properties or variables), and where the new something is  
not a library function, then add new syntax along with the semantics.


More information about the Es-discuss mailing list