-
Notifications
You must be signed in to change notification settings - Fork 2
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
Can we use _
(underscore) instead of void
?
#11
Comments
It's an existing invariant that |
That is a fair point. |
Updated. See the sections marked "What about |
@rbuckton I don't see what I consider to be the main benefit of |
This is covered by the proposal in the OP. I am not restricting this to |
Yes and in my example you could also rename the inner |
I would argue it has roughly the same semantics as renaming any variable in JS has. It does not introduce a new hazard. |
After some discussion with the Pattern Matching champions and further consideration on my part, the plan I intend to propose in the October plenary session is to continue with However, I do plan to discuss the possibility of introducing the duplicate identifiers mechanism as an optional alternative in addition to |
Personally I don't think it's a big problem, it seems developers rarely use AssignmentPattern (because syntax
Could you say more about this? Why we can't make a special case for |
An overwhelming majority of programming languages with a "Discard"-like concept use
_
as the discard marker, including C#, F#, Python, Rust, Go, and now Java, so there has been some interest in whether it might be possible to pursue_
in ECMAScript as well.The Problem
In ECMAScript
_
is a legal identifier which makes it difficult to reserve for this purpose without potentially "breaking the web". Popular packages likeunderscore
andlodash
are frequently referenced using_
, including in the package documentation:Documentation for
_.each()
in Underscore.jsThere is regular pushback against repurposing any identifier in ES as a result of these concerns, so it is unlikely we can follow any kind of deprecation path for
_
as did, for example, Java in its implementation.Allow Duplicate Names: A Possible Solution?
As I have briefly discussed in both the April and June 2024 plenary sessions, there is a potential path forward to use
_
for discards, though not without some limitations. One way in which we could enable this behavior is to make a change to the semantics for duplicate lexical bindings. Today, we have a static semantics rule that results in an early error if you declare a lexical binding with the same name as another lexical binding in the same block scope, or the same name as a "var" declared name in the same "var" scope, as well as a rule to produce an early error if you duplicate a parameter name in a strict function parameter list:Since these are already errors, there is no code that currently executes successfully in these conditions, and it's unlikely that any code has a dependency on this behavior. As a result, we could relax this restriction and allow lexical bindings to be duplicated, but have such duplication poison the binding name in the current lexical environment:
What about
underscore
/lodash
?Rather than restrict this to
_
, we can enforce these rules for all identifiers. This means that you could use__
or___
orfoo
or any other variable name you want as a discard without shadowing an outer_
declaration.What about
typeof
?Since
typeof
is intended to work even for undeclared variables, it is expected thatwould print
"undefined"
just as it would if_
were not declared.What about shadowing?
While
typeof
might treat_
inlet _, _
as if it were not declared, we are still creating a poisoned binding in the current environment, which means that_
remains poisoned in nested scopes. However, a redeclaration in a nested scope would shadow the poisoned binding:Advantages
This approach has several advantages:
void
keyword.Disadvantages
Unfortunately, this is not a complete solution as there are several disadvantages over
void
:_
at the top level of a Script becomes a globalCannot be used as a discard in an AssignmentPattern
Any IdentifierReference in an AssignmentPattern must still be a valid assignment target. Since
_
is still treated as a regular identifier, an assignment pattern like{ x: _, y: _, ...z } = obj
would still attempt to write to an identifier named_
. Rather than acting as a discard, that would either (a) overwrite an existing variable named_
, (b) introduce a new global variable (in non-strict code), or (c) throw due to a missing declaration (in strict code).Since that is very context-dependent, it is inherently unsafe to ignore the error in (c), so we cannot loosen this restriction like we could for lexical bindings.
Cannot be used as-is in pattern matching
In pattern matching an identifier that is not property name must be an IdentifierReference. As a result, a pattern like
would actually be matching the values of the
x
andy
properties to whatever the value of_
is, so we would not be able to use_
as-is as a discard.Instead, we would have to leverage
let
patterns as proposed by the pattern matching proposal, e.g.,, which is far less ideal.
A single
_
at the top level of a Script becomes a globalThe purpose of a discard is to evaluate but not bind, however the following introduces a global
_
variable:Users might mistakenly assume that
_
was actually a discard when in fact it introduced a global variable that is visible to all code running on the page. This can be mitigated by forcibly poisoning the declaration via, e.g.,let _, _;
, but that is not going to be obvious to most developers.The text was updated successfully, but these errors were encountered: