Skip to content

Pipeline-operator for inline invocation of static functions. #43

Open
@lrhn

Description

@lrhn

Solution to #40. This is not a full proposal, just a primer for discussion.

A very simple solution to making static functions easier to use in long chains of invocations, is to allow them to be used in-line.

The "pipelie" operator (e.g., JavaScript strawman, F#) is, at its simplest, just an infix operator taking first an object and then a unary function, and then calling the function with the object. Example:

let double(s: string) = string + string
"42" |> double |> printfn  // prints "4242\n"

Dart can define a similar operator (|> is an option, so is .>, :> or ->).

The F# language is very functional, more than dart, and the pipe operator is one of a number of function composition operators.
In Dart, we want to allow easy chaining of object operations, so the operator should bind as tightly as .. That makes parsing harder if just writing e1 |> foo.bar. Does it mean foo(e1).bar or foo.bar(e1)?
So, it is probably easier to parse if we require parentheses.

Example: something|>function().foo is the same as function(something).foo (except that something is evaluated before function, we do want a consistent left-to-right evaluation). Likewise something|>foo.bar() is similar to foo.bar(something) - the |> binds to the next argument block.

If we always have the parentheses, then we can also add more arguments:
e1|>foo(2, 3) is the same as foo(e1, 2, 3). We could put the pre-pipe expression as the last argument instead of the first, but we want to treat the first expression like a kind of "receiver" for the function, and that object should be the one that's always required by the function, so we put it first.
Both are really reasonable, we just have to pick one.

Examples:

String double(String x) => x + x;
var x= someList.map((x) => "$x").firstWhere(someTest)|>double().indexOf("foo");

Since the syntax is just syntactic sugar for a static function call, type inference can likely not treat the first argument different from the other arguments. Type inference for will have to proceed normally. The type of the first parameter of the function can be used as context type for the first pipe operand expression.

This is a very simple idea, compared to static extension methods (#41) or static extension types (#42).
It has the advantage of working with any static function, not just one explicitly written as an extension method. It has the disadvantage of using a different syntax to call the function.

Metadata

Metadata

Assignees

Labels

featureProposed language feature that solves one or more problemsstate-backlog

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions