Name | Status | Features | Purpose |
---|---|---|---|
Core Proposal | Stage 0 | Infix pipelines … |> … Lexical topic # |
Unary function/expression application |
Additional Feature BC | None | Bare constructor calls … |> new … |
Tacit application of constructors |
Additional Feature BA | None | Bare awaited calls … |> await … |
Tacit application of async functions |
Additional Feature BP | None | Block pipeline steps … |> {…} |
Application of statement blocks |
Additional Feature PF | None | Pipeline functions +> |
Partial function/expression application Function/expression composition Method extraction |
Additional Feature TS | None | Pipeline try statements |
Tacit application to caught errors |
Additional Feature NP | None | N-ary pipelines (…, …) |> … Lexical topics ## , ### , and ... |
N-ary function/expression application |
ECMAScript No-Stage Proposal. Living Document. J. S. Choi, 2018-12.
This document is not yet intended to be officially proposed to TC39 yet; it merely shows a possible extension of the Core Proposal in the event that the Core Proposal is accepted.
With the Core Proposal only, all try
statements’ catch
clauses would
prohibit the use of the topic reference within their steps, except where the
topic reference #
is inside an inner pipeline inside the catch
clause: this
is one of the Core Proposal’s early errors mentioned above.
This additional feature – Pipeline try
Statements – would add new forms of
the try
statement, the catch
clause, and the finally
clause, in the form
of try |> …
, catch |> …
, and finally |> …
, each followed by a pipeline
with the same smart step syntax.
The developer must opt into this behavior by using a
pipeline token |>
, followed by the pipeline. No existing code would be
affected. Any, some, or none of the three clauses in a try
statement may be in
a pipeline form versus the regular block form.
A pipeline try |> …
statement or a finally |> …
clause would apply the outer
context’s topic to their pipelines. As usual, it would be an early error if
the outer context has no topic binding.
A pipeline catch |> …
clause would treat its caught error as if it were the
pipeline’s head value.
With Additional Feature BP, this syntax which would naturally allow the form
catch |> { … }
, except, within the block, the error would be #
.
In addition, a bare catch
form, completely lacking a parenthesized antecedent,
has already been proposed as optional catch
binding. This bare form is
mutually compatible with Additional Feature TS.
Additional Feature TS is formally specified in in the draft specification.
With smart pipelines | Status quo |
---|---|
The example below also uses Additional Feature BP. The The value
|> f
|> {
try |> 1 / #;
catch |> processError;
}
|> g; The semicolons after |
let _1;
try {
_1 = 1 / f(value);
}
catch (error) {
_1 = processError(error);
}
g (_1, 1); |
value
|> f
|> {
try |> 1 / #;
catch |> #.message;
}
|> g(#, 1); Now the |
let _1;
try {
_1 = 1 / f(value);
}
catch (error) {
_1 = error.message;
}
g (_1, 1); |
value
|> f
|> {
try
|> 1 / #;
catch
|> #.message |> capitalize;
}
|> g(#, 1); Pipeline |
let _1;
try {
_1 = 1 / f(value);
}
catch (error) {
_1 = capitalize(error.message);
}
g (_1, 1); |
This pipeline value
|> f
|> {
try |> 1 / #;
catch |> {
#.message |> capitalize;
}
}
|> g; A |
let _1;
try {
_1 = 1 / f(value);
}
catch (error) {
_1 = capitalize(error.message);
}
g (_1, 1); |
If the developer includes the parenthesized parameter (like value
|> f
|> {
try { 1 / #; }
catch (error) {
#.message |> capitalize;
}
}
|> g(#, 1);
// 🚫 Syntax Error:
// Lexical context `catch { … }`
// contains a topic reference
// but has no topic binding. This sort of opt-in behavior is a goal of this proposal and helps ensure that the developer does not [shoot themselves in the foot][“don’t shoot me in the foot”] by accidentally using the topic value from an unexpected outer environment. | |
value
|> f
|> {
try { 1 / #; }
catch {
#.message |> capitalize;
}
}
|> g(#, 1);
// 🚫 Syntax Error:
// Lexical context `catch { … }`
// contains a topic reference
// but has no topic binding. This opt-in behavior is mutually compatible with the proposal for optional
| |
value
|> f
|> {
try |> JSON.parse;
catch |> { message: #.message };
}
|> g(#, 1); |
let _1;
try {
_1 = 1 / f(value);
}
catch (error) {
_1 = { message: error.message };
}
g (_1, 1); |