I haven't been able to come up with a good, self-explanatory name for this feature, yet.
When evaluating the comma operator, automatically assign the result of each evaluated operand to a binding named var
. It can then be used in the next operand.
A few contrived examples
// get a value that can be null, provide default only when undefined
const opt = (getConfigValue('opt'), var === undefined ? 'default' : var);
// use computed value in multiple conditions, without using a temporary variable
if (calculate(stuff), var % 2 === 0 || var % 3 === 0) ...
(var, 1); // throws ReferenceError
// var is uninitialized before the first comma
(1, var + 2); // returns (1 + 2) -> 3
(1, (var + 2, var * 3)); // returns ((1 + 2) * 3) -> 9
// in a nested comma operator, var before the first comma
// refers to the outer sequence's var;
// this ensures that removing superfluous parentheses works
// as expected: (X, (Y, Z)) must be equivalent to (X, Y, Z)
// and so the above expression gives the same result as:
(1, var + 2, var * 3);
('A', (var + 'b', var + 'c') + (var + 'x', var + 'y'))
// returns (('A' + 'b') + 'c') + (('A' + 'x') + 'y') -> 'AbcAxy'
Mimic Hack-style pipeline, using var
as topic token and ,
instead of |>
Examples taken from GitHub - js-choi/proposal-hack-pipes: Draft specification for Hack pipes in JavaScript.
return list
, take(prefix.length, var)
, equals(var, prefix);
envars
, Object.keys(var)
, var.map(envar =>
`${envar}=${envars[envar]}`,
)
, var.join(' ')
, `$ ${var}`
, chalk.dim(var, 'node', args.join(' '))
, console.log(var);
There's a caveat, though. Hack-style pipeline can use topic in a nested function:
2 |> [1, 2, 3].map(x => x ** #)
// returns [1, 4, 9]
I deliberately chose to restrict the var
binding to the comma operator, and not allow referencing it from nested scope (more precisely, nested scope has its own uninitialized var
binding):
2, [1, 2, 3].map(x => x ** var)
// throws ReferenceError: 'var' cannot be used before initialization
This can of course be changed if carrying the binding into closures is considered useful. For now I did it this way because I think it's less confusing, and also easier to implement.
PoC implementation
To try it out:
git clone --depth 10 --branch feat-var-expression \
https://github.com/lightmare/engine262
cd engine262
pnpm install
pnpm run build
node bin/engine262.js --features=var-expression