ECMAScript Stage-0 Proposal. Living Document. J. S. Choi, 2018-12.
Most pipeline steps will use topic references in their steps. This style of pipeline step is called topic style.
For three simple cases – unary functions, unary async functions, and unary constructors – you may omit the topic reference from the pipeline step. This is called bare style.
When a pipe is in bare style, we refer to the pipeline as a bare function
call. The step acts as just a simple reference to a function, such as with … |> capitalize
or
with … |> console.log
. The step’s value would then be called as a unary
function, without having to use the topic reference as an explicit argument.
The two bare-style productions require no parameters, because they can only be
simple references, made up of identifiers and dots .
. (There are optional
Additional Features that extend these style in
limited ways for further convenience. These Additional Features are not part of this
Core Proposal but rather show possible future extensions.)
Valid topic style | Valid bare style | Invalid pipeline |
---|---|---|
… |> f(#) |
… |> f |
… |> f() 🚫 |
″″ | ″″ | … |> (f) 🚫 |
″″ | ″″ | … |> (f()) 🚫 |
… |> o.f(#) |
… |> o.f |
… |> o.f() 🚫 |
… |> o.f(arg, #) |
const f = $ => o::f(arg, $); … |> f |
… |> o.f(arg) 🚫 |
… |> o.make()(#) |
const f = o.make(); … |> f |
… |> o.make() 🚫 |
… |> o[symbol](#) |
const f = o[symbol]; … |> f |
… |> o[symbol] 🚫 |
The bare style supports using simple identifiers, possibly with chains of simple property identifiers. If there are any operators, parentheses (including for method calls), brackets, or anything other than identifiers and dot punctuators, then it is in topic style, not in bare style.
If the pipeline step is a merely a simple reference, then that identifier is interpreted to be a bare function call. The pipeline’s value will be the result of evaluating the step as an identifier or member expression, then calling the result as a function, with the current topics as its arguments.
That is: if a pipeline is of the form
topic |>
identifier
or topic |>
identifier0.
identifier1
or topic |>
identifier0.
identifier1.
identifier2
or so forth,
then the pipeline is a bare function call.
The presence or absence of topic tokens (#
, ##
, ###
) is not used in the
grammar to distinguish topic style from bare style to fulfill the goal of
syntactic locality. Instead, if a pipeline step of the form
|> step does not match the bare style (that is, it is not a bare
function call, bare async function call, or bare constructor call), then it
must be in topic style. Topic style requires that there be a topic
reference in the pipeline step; otherwise it is an early error.
A pipeline step that is not in bare style is usually a topic expression. This is any expression at the precedence level once tighter than pipeline-level expressions – that is, any conditional-level expression.
Therefore, a pipeline step in bare style never contains parentheses (…)
or
brackets […]
. Neither … |> object.method()
nor
… |> object.method(arg)
nor … |> object[symbol]
nor … |> object.createFunction()
are in bare style (in fact, they all are Syntax Errors, due to their being in
topic style without any topic references).
When a pipeline step needs parentheses or brackets, then don’t use bare style, and instead use a topic reference in the step (topic style)…or assign the step to a variable, then use that variable as a bare-style step.
As a infix operation forming compound expressions, the operator precedence and associativity of pipelining must be determined, relative to other operations.
Precedence is tighter than arrow functions (=>
), assignment (=
, +=
, …),
generator yield
and yield *
, and sequence ,
; and it is looser than every
other type of expression. If the pipe operation were any tighter than this
level, its steps would have to be parenthesized for many frequent types of
expressions. However, the result of a pipeline is also expected to often serve
as the body of an arrow function or a variable assignment, so it is tighter than
both types of expressions.
All operation-precedence levels in JavaScript are listed here, from tightest to loosest. Each level may contain the parse types listed for that level – as well as any expression types from any precedence level that is listed above it.
Level | Type | Form | Associativity / fixity |
---|---|---|---|
Primary | This | this |
Nullary |
″″ | Primary topic | # |
″″ |
″″ | Secondary topic | ## |
″″ |
″″ | Tertiary topic | ### |
″″ |
″″ | Rest topic | ... |
″″ |
″″ | Identifiers | a … |
″″ |
″″ | Null | null |
″″ |
″″ | Booleans | true false |
″″ |
″″ | Numerics | 0 … |
″″ |
″″ | Arrays | […] |
Circumfix |
″″ | Object | {…} |
″″ |
″″ | Function | function (…) {…} |
″″ |
″″ | Classes | class … {…} |
″″ |
″″ | Generators | function * (…) {…} |
″″ |
″″ | Async functions | async function (…) {…} |
″″ |
″″ | Regular expression | /…/… |
″″ |
″″ | Templates | …`…` |
″″ |
″″ | Parentheses | (…) |
Circumfix |
LHS | Static properties | ….… |
″″ |
″″ | Dynamic properties | …[…] |
LTR infix with circumfix |
″″ | Tagged templates | …`…` |
Unchainable infix with circumfix |
″″ | Super call op.s | super(…) |
Unchainable prefix |
″″ | Super properties | super.… |
″″ |
″″ | Meta properties | meta.… |
″″ |
″″ | Object construction | new … |
Prefix |
″″ | Function call | …(…) |
LTR infix with circumfix |
Postfix unary | Postfix incrementing | …++ |
Postfix |
″″ | Postfix decrementing | …-- |
″″ |
Prefix unary | Prefix incrementing | ++… |
RTL prefix |
Prefix unary | Prefix decrementing | --… |
″″ |
″″ | Deletes | delete … |
″″ |
″″ | Voids | void … |
″″ |
″″ | Unary + /- |
+… |
″″ |
″″ | Bitwise NOT ~… |
~… |
″″ |
″″ | Logical NOT !… |
!… |
″″ |
″″ | Awaiting | await … |
″″ |
Exponentiation | Exponentiation | … ** … |
RTL infix |
Multiplicative | Multiplication | … * … |
LTR infix |
″″ | Division | … / … |
″″ |
″″ | Modulus | … % … |
″″ |
Additive | Addition | … + … |
″″ |
″″ | Subtraction | … - … |
″″ |
Bitwise shift | Left shift | … << … |
″″ |
″″ | Right shift | … >> … |
″″ |
″″ | Signed right shift | … >> … |
″″ |
Relational | Greater than | … < … |
″″ |
″″ | Less than | … > … |
″″ |
″″ | Greater than / equal to | … >= … |
″″ |
″″ | Less than / equal to | … <= … |
″″ |
″″ | Containment | … in … |
″″ |
″″ | Instance-of | … instanceof … |
″″ |
Equality | Abstract equality | … == … |
″″ |
″″ | Abstract inequality | … != … |
″″ |
″″ | Strict equality | … === … |
″″ |
″″ | Strict inequality | … !== … |
″″ |
Bitwise AND | … & … |
″″ | |
Bitwise XOR | … ^ … |
″″ | |
Bitwise OR | … | … |
″″ | |
Logical AND | … ^^ … |
″″ | |
Logical OR | … || … |
″″ | |
Conditional | … ? … : … |
RTL ternary infix | |
Pipeline | Pipelines | … |> … |
LTR infix |
Assignment | Pipeline functions | +> … |
Prefix |
″″ | Async pipeline functions | async +> … |
Prefix |
″″ | Arrow functions | … => … |
RTL infix |
″″ | Async arrow functions | async … => … |
RTL infix |
″″ | Assignment | … = … |
″″ |
″″ | … += … |
″″ | |
″″ | … -= … |
″″ | |
″″ | … *= … |
″″ | |
″″ | … %= … |
″″ | |
″″ | … **= … |
″″ | |
″″ | … <<= … |
″″ | |
″″ | … >>= … |
″″ | |
″″ | … >>>= … |
″″ | |
″″ | … &= … |
″″ | |
″″ | … |= … |
″″ | |
Yield | Yielding | yield … |
Prefix |
″″ | Flat yielding | yield * … |
″″ |
″″ | Spreading | ...… |
″″ |
Comma level | Comma | …, … |
LTR infix |
Base statements | Expression statements | …; |
Postfix with ASI |
″″ | Empty statements | ; |
Nullary with ASI |
″″ | Debugger statements | debugger; |
″″ |
″″ | Block statements | {…} |
Circumfix |
″″ | Labelled statements | …: … |
Prefix |
″″ | Continue statements | continue …; |
Circumfix with ASI |
″″ | Break statements | break …; |
″″ |
″″ | Return statements | return …; |
″″ |
″″ | Throw statements | throw …; |
″″ |
″″ | Variable statements | var …; |
″″ |
″″ | Lexical declarations | let …; |
″″ |
″″ | ″″ | const …; |
″″ |
″″ | Hoistable declarations | function … (…) {…} |
Circumfix with prefix |
″″ | ″″ | async function … (…) {…} |
″″ |
″″ | ″″ | function * … (…) {…} |
″″ |
″″ | ″″ | async function * … (…) {…} |
″″ |
″″ | Class declarations | class … {…} |
″″ |
Compound statements | If statements | if (…) … else … |
Circumfix with prefix |
″″ | Switch statements | switch (…) … |
″″ |
″″ | Iteration statements | ″″ | |
″″ | With statements | with (…) {…} |
″″ |
″″ | Try statements | try {…} catch (…) {…} finally {…} |
″″ |
Statement list | Case clause | case: … |
Unchainable prefix |
Root | Script | Root | |
″″ | Module | ″″ |