-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: Introduce let
statement.
#5445
Comments
This sounds cool! (if somewhat hard to implement) A nice feature is that One note is that I also find it a little weird that I've also long been a proponent of For what it's worth, Civet supports |
For code generation of the a = 1
b = (x) ->
let a
let y = 2
---
var a, b;
a = 1;
b = function (x) {
var y;
const a1 = a;
{
let a = a1;
y = 2;
}
}; That way only a transient ref is needed rather than relabeling all identifiers in a scope. |
I prefer implicit const with no parentheses and no commas: fn = x1 x2 -> x1 * lg x2
---
const fn = (x1, x2) => x1 * Math.log(x2) |
That’s ambiguous. You’re breaking pretty much every single callback in coffee. |
I was so sure const a1 = a;
{
let a = a1;
// ...
} Both options kinda suck. Could still collapse multiple Edit: I think it's fine. The user gets correct variable names and downstream tooling can strip the block. (minification, dead code elimination, etc) |
Not being able to shadow variables in an upper scope or a calling function is a PITA. In MoonScript, which is to Lua what CS is to JS, all variables not initialized or declared in an upper scope are local by default unless explicitly made global with Unlike JS/CS variables declared in calling functions are thankfully not visible in called functions in Lua/MS (unless the callee is a closure within the caller) but MS has the Footnotes
|
I have introduced a non-breaking change which makes CoffeeScript aware of block scope: #5475. I believe this is a necessary prerequisite for this feature request. Please take a look if interested! |
Do you have thoughts on a
let
keyword for coffeescript?Let me walk you through my idea below.
It could be syntactic sugar for the current
do (a, b, x) =>
expression, while avoiding extra indentation, like this:In current coffeescript this can almost be expressed like so:
But as annotated, this loop becomes a problem when the loop body (the IIFE's body) uses the
await
keyword because that changes the return type offunc
, from a Promise that will resolve to an Array, to an (already resolved) Array of Promises. The loop's iterations now run in parallel. If you did not intend for this you now have a critical bug, at least waiting to happen.So really it would have to be this code to preserve meaning:
In above example the
let
keyword eliminates the syntactic cruft necessary to express the same scoping rules in a bug-free manner, making it easy to write correct code. It also enables the loop to be a generator and to return fromfunc
early by not introducing a new function boundary.Also, if above code used slim arrows
->
instead of fat ones (=>
), the potentialthis
association is lost. Another thing to watch out for.Context
There have been many requests to support JS'
let
andconst
with the primary driver being finer control over variable scopes.The
let
"statement" proposed here addresses general scoping concerns in a readable manner. I'd define its rules like this:var
declaration to the enclosing function body if applicable, generating an in-placelet
instead.undefined
. (a = let b
is illegal)let a = 1, b, c = 4
)let
more than once with the same identifier in the same block scope by generating a{ let ... }
block, but this is maybe unintentional. Without this, an explicitdo =>
andlet
can still be used when needed, exposing the user to the usual pitfalls associated with it (e.g. having to conditionallyawait do =>
).let
would solve this automagically but arguably it's a corner case and the compile error may be preferred.Simply put, the proposed
let
statement outputs a JSlet
statement. But additionally it initializes to the shadowed identifier's value, if any:Input:
Output:
Possible future extensions include other assignment operators, which could operate on the shadowed identifier's value to initialize the local capture.
Conclusion
This proposal gives people their block scoping and offers a readable, unambiguous solution to common variable capturing issues, avoiding the pitfalls and mental overhead associated with current workarounds.
It also supersedes
do (a, b = 1) =>
expressions. They can now be expressed as:The text was updated successfully, but these errors were encountered: