Skip to content

Proposal: Hack-style Pipelining #84

@zenparsing

Description

@zenparsing

The current proposal (in which the RHS is implicitly called with the result of the LHS) does not easily support the following features:

  • Piping into a function with multiple arguments
  • Calling methods on a piped value
  • Awaiting a piped value

In order to better support these features the current proposal introduces special-case syntax and requires the profilgate use of single-argument arrow functions within the pipe.

This proposal modifies the semantics of the pipeline operator so that the RHS is not implicitly called. Instead, a constant lexical binding is created for the LHS and then supplied to the RHS. This is similar to the semantics of Hack's pipe operator.

Runtime Semantics

PipelineExpression : PipelineExpression |> LogicalORExpression
  1. Let left be the result of evaluating PipelineExpression.
  2. Let leftValue be ? GetValue(left).
  3. Let oldEnv be the running execution context's LexicalEnvironment.
  4. Let pipeEnv be NewDeclarativeEnvironment(oldEnv).
  5. Let pipeEnvRec be pipeEnv's EnvironmentRecord.
  6. Perform ! pipeEnvRec.CreateImmutableBinding("$", true).
  7. Perform ! pipeEnvRec.InitializeBinding("$", leftValue);
  8. Set the running execution context's LexicalEnvironment to pipeEnv.
  9. Let right be the result of evaluating LogicalORExpression.
  10. Set the running execution context's LexicalEnvironment to oldEnv.
  11. Return right.

Example

anArray
  |> pickEveryN($, 2)
  |> $.filter(...)
  |> shuffle($)
  |> $.map(...)
  |> Promise.all($)
  |> await $
  |> $.forEach(console.log);

Advantages

  • All use cases described above are supported with no special-case syntax.
  • By removing the implicit-call behavior, we remove a potential source of confusion for developers.

Disadvantages

  • By requiring an explicit function call, functional programming patterns that rely heavily on currying will be less ergonomic.

Notes

The choice of "$" for the lexical binding name is somewhat arbitrary: it could be any identifier. It should probably be one character and should ideally stand out from other variable names. For these reasons, "$" seems ideal. However, this might result in a conflict for users that want to combine both jQuery and the pipeline operator. Personally, I think it would be a good idea to discourage usage of "$" and "_" as variable names with global meanings. We have modules; we don't need jQuery to be "$" anymore!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions