Skip to content
This repository has been archived by the owner on Jan 26, 2022. It is now read-only.

Latest commit

 

History

History
499 lines (457 loc) · 24.2 KB

additional-feature-ts.md

File metadata and controls

499 lines (457 loc) · 24.2 KB
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

Additional Feature TS

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 try clause is in the pipeline form using the topic style. It applies the expression 1 / # to the outer context’s topic (in this case, f(value)).

The catch clause is also in the pipeline form using the bare style. It applies the function processError to the caught error.

value
|> f
|> {
  try |> 1 / #;
  catch |> processError;
}
|> g;

The semicolons after 1 / # and after processError are optional. There is no ASI hazard here because pipeline steps may never contain a catch or finally clause, unless the clause is inside a block.

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 catch clause is also in topic style, applying apply console.error as a method call to the caught error.

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 try statements and their clauses may be chained as usual. This pipeline catch clause is in topic style (|> #.message) followed by bare style (|> capitalize).

let _1;
try {
  _1 = 1 / f(value);
}
catch (error) {
  _1 = capitalize(error.message);
}
g (_1, 1);

This pipeline try statement’s catch clause is using the topic-block style from Additional Feature BP.

value
|> f
|> {
  try |> 1 / #;
  catch |> {
    #.message |> capitalize;
  }
}
|> g;

A |> between try and its block { |> 1 / # } is unnecessary, because the outer topic does not need to be rebound. However, it is necessary between catch and its block in order to opt into binding the topic reference to the caught errors.

let _1;
try {
  _1 = 1 / f(value);
}
catch (error) {
  _1 = capitalize(error.message);
}
g (_1, 1);

If the developer includes the parenthesized parameter (like (error) in this example) or if they leave out the |> after the catch, then no topic binding is established. As per the early error rules in Core Proposal, topic references are not allowed in regular catch blocks.

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 catch binding.

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);