@aaditmshah Apologies for my limited expertise in functional programming. How is your first example different from using normal let statements?
const x = Math.random();
const y = x * x + 2;
const z = y * 3;
const a = z.toString();
And the difference with the proposed as expression I can think of is that the data flow in let expression can be a DAG rather than a pipeline:
const a =
const x = Math.random() in
const y = x * x in
const z = x + 2 in
(y + z);
But in this case, I think we should fall back to the normal control flow to explicitly state the data dependency.
I can't speak for the usefulness of let expressions. But from the software engineering perspective, let expressions violate a principle (or coincidence) of declaring variables and make it harder to find the declaration of variables. I can peek at a line and quickly know there's a declaration if the line starts with let, const, import, for, function, etc. I could find every local declaration with the regex ^\s*const . Now how about this?
console.log("The sum of two numbers is ", a, "+", b, "=", const c = a + b in c);
This is Pandora's box that requires serious consideration before opening.
Another problem with let expressions is the scope problem. Should the const variable be available outside the declaration ()? That's something a developer cannot infer from the syntax, and one has to look up the spec if it has moved to another language to work on a project for some weeks and just moved back to JS.
The scope problem is something I would personally avoid. JS once had the infamous var declaration:
console.log(foo); // undefined
if(true) {
var foo = "bar";
}
console.log(foo); // bar
@theScottyJam The % variable in the pipeline proposal brings this problem back, in an inversed way. The scope might appear to be different than expected:
const a = 1 |> (2 |> % * %);
How do we distinguish (2 |> %) * % and 2 |> (% * %)? Again, we need to look up the operator precedence before we can be sure. It's not a well-known precedence like + and *. It's JS-specific.
Of course, you are able to write correct code if you are careful, just as how you know the scope problem of var. But we want it to be obvious, and so obvious that we can grab a piece of code and understand what it is exactly doing without looking up the spec.
@markm This is really an intriguing trick! As for the difference:
- The
as expressions & do expressions have the extra power of embedding for and if statements.
- The
as expressions & do expressions can use await, while function parameters cannot.
It is a Syntax Error if CoverCallExpressionAndAsyncArrowHead Contains AwaitExpression is true.
- The
as expression & the pipeline proposal can discard temporary variables for GC.
- The
as expression & the pipeline proposal also enable clean refactor history in line diff (e.g. git). This is also the purpose of trailing commas, I believe. const a = ((
x = Math.random(),
- y = x * x + 2,
- z = y * 3
+ z = x * 3,
) => z.toString()
)();
const a = Math.random()
- as(x) { x * x + 2 }
as(x) { x * 3 }
.toString();