I don't expect this probably has any place in ECMAScript (sadly) because I can't figure out a way to syntax it without it being confusing, but I wanted to get some input on a nice-to-have that I've wanted for some time now. The idea is to change the semantics of return
to be a unary prefix operator of lowest precedence that:
- evaluates to its argument
- stores its argument in the current function's "return slot"
- triggers end-of-function at the end of the current statement
Which is a strict superset of the current return semantics. The times when I wish for it hardest are when I'm debugging and I want to trace function entry/exit:
// original function:
function sumOrNone(x, y) {
if (x === null) return y;
if (y === null) return x;
return x + y;
}
//add debug tracing, return-as-expression syntax:
function sumOrNone(x, y) {
console.log("Called sumOrNone with arguments:", {x, y});
if (x === null) console.log("x is null, returning y:", return y);
if (y === null) console.log("y is null, returning x:", return x);
console.log("neither is null, adding", return x + y);
}
//add debug tracing, current syntax:
function sumOrNone(x, y) {
console.log("Called sumOrNone with arguments:", {x, y});
if (x === null) {
console.log("x is null, returning y:", y);
return y;
}
if (y === null) {
console.log("y is null, returning x:", x);
return x;
}
const rv = x + y;
console.log("neither is null, adding", rv);
return rv;
}
With return-as-expression, if I have a function with a ton of return statements, I can instantly add logging to every one of them with a single find/replace. As it is now, I have to add braces, store return values, etc.
The downside is that it becomes harder to find which statements are possible function returns, as "return" can become buried and/or fall off the right edge of the screen, but that comes down to code style - it's already possible to put return in weird places, especially if you combine multiple statements per line. Not to mention, of course, that the semantics would need some serious hammering-on, like, what happens when a return expression is part of an await? What happens when you have multiple return expressions in a single statement?
I can't think of any direct piece of prior art, but C#'s throw
expressions are similar (usually as a way to "abort with exception if this parameter is invalid", and return
expressions could be used in a similar way for a more graceful function abort. The difference between the two is pretty huge, though: throw
always aborts instantly, whereas return
-as-expression has to defer the return until after the current statement is complete.
Thoughts?