let function
Why not use a function declaration instead?
I guess 'cause that cannot be scoped, let's say in a for loop ... but yeah, I think that's not the most needed thing in the language right now, yet another shortcut with double reserved words one after the other
They can, in fact, be scoped in a for loop.
Yep, that's the reason. It's invalid with 'use strict' to put function declarations inside an if or for block, and function declarations get hoisted.
Alternatively, as we have object shorthand notation, e.g.
{
foo() {},
}
that does not require the function keyword, yet still acts like a function, expresses a property named foo that is a function with name property "foo". So maybe in the same spirit we could also consider
let foo() {};
But generators would look a bit weird without the function keyword...!
let *foo() {}
Agree this is not exactly the most pressing issue, but it seems easy to implement as it has trivial equivalence to existing language (unforeseen grammar ambiguities notwithstanding!), and having to repeat the name when defining scoped functions is a bit of a wart IMO.
Yep, that's the reason. It's invalid with 'use strict' to put function declarations inside an if or for block
This is just false.
That's not what I see, in strict mode at least, which I assume most people consider de facto by now!
From V8:
SyntaxError: In strict mode code, functions can only be declared at top
level or immediately within another function.
Similar error from SpiderMonkey.
Not all browsers have implemented the spec yet. But you should read the spec before proposing changes to it!
Hay, I've not read all of the spec, and I've implemented much of it. :P
not, in fact, in a backward compatible way, unless transpiled.
Alexander Jones schrieb:
On Thursday, May 14, 2015, Domenic Denicola <d at domenic.me> wrote:
They can, in fact, be scoped in a for loop.
That's not what I see, in strict mode at least, which I assume most people consider de facto by now!
From V8:
SyntaxError: In strict mode code, functions can only be declared at top
level or immediately within another function.
That's ES5. In ES6, function declarations are allowed in blocks - with the new block scope semantics. This was only possible as ES5 strict mode held that spot open so now it doesn't break anything :-) Yes, it will need a while until people get accustomed to that.
Bergi
Ah, thanks for explaining! What about the Temporal Dead Zone of let, or const binding semantics, for those of us who are obsessive enough to desire that kind of thing everywhere?
like I've replied to Domenic, you need to transpile if you want function declaration block-scoped backward compatible and all other ES6 goodies.
babeljs would be my pick: babeljs.io
Best
On 5/14/15, Alexander Jones <alex at weej.com> wrote:
Ah, thanks for explaining! What about the Temporal Dead Zone of let, or const binding semantics, for those of us who are obsessive enough to desire that kind of thing everywhere?
Let a constructive discussion about this proposal take place.
"The specification," can most reasonably be taken among programmers to mean "the latest version of specification" not "draft specification" or "proposal". Evangelists and standards geeks tend to miscall "draft" "specification" to the misfortunate effect that it misleads developers into believing that drafts are normative, final, etc. That's quite a bit worse than the abrasiveness and confusion seen here, but hopefully they can stop and a discussion can take place.
www.ecma-international.org/ecma-262/5.1/#sec-12
Because of these irreconcilable differences, the use of a FunctionDeclaration as a Statement results in code that is not reliably portable among implementations. It is recommended that ECMAScript implementations either disallow this usage of FunctionDeclaration or issue a warning when such a usage is encountered.
The decision for such wording probably came from discussions and time constraints of getting ES5 done. The problem of FunctionDeclaration arose from implementations in JScript (see "[MS-ES3EX]" and language extensions in Spidermonkey and others. It progressed to misstatements in presentations and books. For more on this, see "Named function expressions demystified".
Good points. All the more reason to throw out declarations as statements in favour of let/const/var, which we all have to understand well anyway, for other types of variable.
I proposed something similar to this among the folks investigating decorators for ES7:
In this case, it was for a const function
, as a means to allow a decorator on a function declaration, as adding the const
(or let
) would introduce TDZ and set the right expectations for how decorators would be executed.
Good points. All the more reason to throw out declarations as statements in favour of let/const/var, which we all have to understand well anyway, for other types of variable.
Declarations aren't going anywhere, and there is zero interest in "deprecating" them. You might want to spend a bit more time learning the spec or lurking before making proposals.
Hope that helps.
When I said throw out, I didn't mean deprecate. I meant like 'let is the new var' - an entirely optional programming choice.
I'm not sure what warrants that kind of hostility, but I knew enough of the spec to know that 'use strict' prohibited function declarations as statements, and that let and const had attractive, sound and intuitive semantics. I'm sorry if you feel that's an inappropriate basis for a mailing list post, but I disagree.
On May 14, 2015, at 12:40 PM, Alexander Jones wrote:
Ah, thanks for explaining! What about the Temporal Dead Zone of let, or const binding semantics, for those of us who are obsessive enough to desire that kind of thing everywhere?
ES6 specifies that function declarations are allowed in blocks in both strict and nn-strict mode. In both cases they are block scoped and have essentially the same semantics (including a TDZ) as a let declaration.
In addition, Annex B people.mozilla.org/~jorendorff/es6-draft.html#sec-block-level-function-declarations-web-legacy-compatibility-semantics provides an extended semantics for block level function declarations in non-strict code. That semantics is for use in implementations that need to provide backwards compatibility with the non-standard block level function declaration behavior that was provided by various browsers.
As Perlis has said: too much syntactic sugar causes cancer of the semicolon. IMO, this is not much of a win given what is now available, especially with arrow functions and shorthand method definitions
On May 14, 2015, at 12:40 PM, Alexander Jones wrote:
ES6 specifies that function declarations are allowed in blocks in both strict and nn-strict mode.
In both cases they are block scoped and have essentially the same semantics (including a TDZ) as a let declaration.
There is no TDZ for block-scoped function declarations. Function declarations are basically hoisted to the top of the block.
On May 14, 2015, at 3:39 PM, André Bargull wrote:
There is no TDZ for block-scoped function declarations. Function declarations are basically hoisted to the top of the block.
Ah right, I misspoke about on that point. block level function declarations are indeed hoisted to the top of the block.
Thanks for sharing. Are there any known, viable alternatives for decorators?
On 5/14/15, Kevin Smith <zenparsing at gmail.com> wrote:
Good points. All the more reason to throw out declarations as statements in favour of let/const/var, which we all have to understand well anyway, for other types of variable.
Declarations aren't going anywhere,
Getting rid of FunctionDeclaration was not proposed.
If the proposed let function
idea is no good, is it because
FunctionDeclaration-as-a-Statement is a better replacement? Or is
there a better reason?
and there is zero interest in
"deprecating" them. You might want to spend a bit more time learning the spec or lurking before making proposals.
You go read the spec and lurk.
Hope that helps.
It obviously doesn't help at all.
Consistency in implementations would help. An easier-to-read ECMAScript specification would also help. Discussions like this can help when they point out the reality of what implementations do vs what the specification and its authors say vs what the so-called experts, and worse (W3Schools, etc) say.
I post this followup with some trepidation, as the es-discuss S/N ratio has dropped badly in recent weeks. Perhaps esdiscourse is doing better? Anyway, discussion fodder: @rauchg messaged me recently wondering why
let f = (x) => y;
could not be shortened to
let f(x) y;
This seems like a better shorthand to discuss, compared to let function
(which function-in-block covers already, as noted).
Brendan Eich proposed:
let f = (x) => y;
could be shortened to
let f(x) y;
Too confusing imo. I'd like to retain the fat arrow that effectively communicates the callability:
let f(x) => y;
It would work fine without parameters as well:
let f() => y;
let f => y;
Alternatively just use a single equals sign with a parameter list:
let f(x) = y let f() = y
(which almost looks like Haskell, hehe).
Bergi
On 05/19/2015 12:23 AM, Alan Schmitt wrote:
On 2015-05-19 06:09, Bergi <a.d.bergi at web.de> writes:
Alternatively just use a single equals sign with a parameter list:
let f(x) = y let f() = y This looks very nice indeed.
That visually collides with destructuring for me.
let [a, b] = foo(); let {a, b} = foo(); let f(a, b) = foo(); # Very different
I almost expect that last one to use f as a custom matcher of some sort, given the previous two.
On Tue, May 19, 2015 at 12:24 PM, Steve Fink <sphink at gmail.com> wrote:
That visually collides with destructuring for me.
let [a, b] = foo(); let {a, b} = foo(); let f(a, b) = foo(); # Very different
I almost expect that last one to use f as a custom matcher of some sort, given the previous two.
Well there's an interesting proposal. As I understand it, this corner of the grammar is free, so custom matchers would be a possibility here.
I can imagine some interesting uses for custom data types, eg:
let pair(a, b) = foo(); // like let {head, tail} = foo();
but with custom
type checking.
let polar(radius, angle) = point(1, 2); // custom matcher can convert
between coordinate respresentations
or even build a simple matching case statement for a recursive decent parser:
let for_statement(init, cond, incr) = input_text;
Does that spark ideas in anyone else?
C. Scott Ananian wrote:
On Tue, May 19, 2015 at 12:24 PM, Steve Fink <sphink at gmail.com <mailto:sphink at gmail.com>> wrote:
That visually collides with destructuring for me. let [a, b] = foo(); let {a, b} = foo(); let f(a, b) = foo(); # Very different I almost expect that last one to use f as a custom matcher of some sort, given the previous two.
Well there's an interesting proposal. As I understand it, this corner of the grammar is free, so custom matchers would be a possibility here.
I can imagine some interesting uses for custom data types, eg:
let pair(a, b) = foo(); // like
let {head, tail} = foo();
but with custom type checking. let polar(radius, angle) = point(1, 2); // custom matcher can convert between coordinate respresentationsor even build a simple matching case statement for a recursive decent parser:
let for_statement(init, cond, incr) = input_text;
Does that spark ideas in anyone else?
Sure, and we've had pattern matching on the agenda for a while (distinct from destructuring in ES6: refutable match, richer pattern language).
harmony:refutable_matching (arossberg: anything newer on github?) strawman:pattern_matching (older strawman from dherman)
I agree that let f(x) = y
encroaches confusingly on pattern matching,
not let-function declaration.
On 19 May 2015 at 02:02, Brendan Eich <brendan at mozilla.org> wrote:
This seems like a better shorthand to discuss, compared to
let function
(which function-in-block covers already, as noted).
function-in-block does not have the same semantics as the proposed "let function". It hoists, thus has no TDZ, and appears to preclude a reasonable decorator syntax behaviour, and it has no provisions for const binding, i.e. "const function".
let f(x) => y
appears attractive indeed, but by virtue of it being an arrow function, has lexical this and no prototype property. Also no generator syntax, unless I'm missing something?
Cheers
function-in-block does not have the same semantics as the proposed "let function". It hoists, thus has no TDZ, and appears to preclude a reasonable decorator syntax behaviour,
But that would not fix the decorator/function problem. Specifically, we would not want to have a situation where "let" functions are decorable but function declarations are not.
and it has no provisions for const binding, i.e. "const function".
A "const function" syntax was proposed during ES6 development and might still be an option.
Yes. I proposed it and plan to do so again. Likewise with const classes. In both cases, it imposes additional tamper-proofing restrictions along the lines of the StrongScript proposal in order to support writing defensively consistent abstractions.
Your point about decorators vs. hoisting is good, everyone should keep it in mind. Still doesn't mean we can't add a special form for const function, as followups aver.
On 2015-05-19 18:24, Steve Fink <sphink at gmail.com> writes:
On 05/19/2015 12:23 AM, Alan Schmitt wrote:
On 2015-05-19 06:09, Bergi <a.d.bergi at web.de> writes:
Alternatively just use a single equals sign with a parameter list:
let f(x) = y let f() = y This looks very nice indeed.
That visually collides with destructuring for me.
let [a, b] = foo(); let {a, b} = foo(); let f(a, b) = foo(); # Very different
I almost expect that last one to use f as a custom matcher of some sort, given the previous two.
It is actually how it works in Ocaml: in "let f p = …", p is a pattern, which may destructure tuples such as the pair (a,b) above, or other constructs as long as they are not part of an alternation (where several cases may occur).
Best,
Alan
Guillermo wondered whether we couldn't have
let f(x) { return x*x; };
as a shorthand for the block-bodied arrow
let f = (x) => { return x * x; }
The obvious question is how to enable expression bodies?
let f(x) x * x;
looks like it is missing the =>, but if we require that:
let f(x) => x * x;
then why not for the block-bodied case too, so readers are better
reminded that this
is from the outer scope, ditto arguments
?
Decisions, decisions!
Propose adding support for
which would have the equivalence of:
The idea is to support the normal scoping of let, but without forcing you to repeat yourself when naming the function, whilst still having the function's name property be set.
This would trivially extend to const and var. Also, possibly class.