Update 1: I was delighted, but not totally surprised that someone else thought this was a good idea – 2 months ago. Patrice Chalin wrote up the proposal on his blog in February and filed a feature request. I've closed my request as a duplicate of his.

Disclaimer: This is not in anyway official. It's an idea. If you're excited about it, great. Please star the associated issue. I'm trying to judge interest in the Dart community.

One of the first Dart issues – the 13th, to be precise – was for C#-style extension methods.

This is not possible in a consistent and performant way due to Dart's type system.

But I'm pretty sure that most Dart developers that want C#-style extension methods would be happy with something much more simple.

Imagine the following code
...
class Foo {
...
  void fooMethod() {
  ...
  var items = [true, null, "Test", 42];
  var isEven = _isEven(countWhere(items, (e) => e is bool));
  }
}

_isEven could be an instance method on Foo, or a static method on Foo, or a top-level method in the current library.

countWhere could also be a instance or static method on Foo, or a top-level method on the current library or an imported library. It could also be a function defined in-line in fooMethod.

Now imagine an alternative syntax for the same behavior, with a new sugar in the form of |> – the method pipe.

...
class Foo {
...
  void fooMethod() {
  ...
  var items = [true, null, "Test", 42];
  var isEven = items |> countWhere((e) => e is bool) |> _isEven();
  }
}

Method pipe is simple. Anything of the form

g(f(expression))

Can be written as

expression |> f() |> g()

Basically, the expression on the left side of |> is passed as the first parameter of the function on the right of |>.

What about multiple arguments? Named arguments?

If you had function

int count(int a, int b, int c, {int d}) { ... }

You can call it as

count(1, 2, 3, d: 4);

or

1 |> count(2, 3, d: 4);

What if you try to call a method that has no default parameters? Or you try to call a field like a method?

The same thing that happens now.
int value = 5;
void run({String arg}) { ... }

// Today: Warning in the analyzer and errors at runtime
value(10);
run("test");

// Tomorrow: Warnings in the analyzer and errors at runtime;
10 |> value();
"test" |> run();

See where I'm going?

The method pipe syntax – |> – is completely up for debate. But I like the model. One could create and import a library full of top-level methods that consume IterablegroupBy, countWhere, wrapWithUnmodifiableList, etc and write.

var items = [1, 2, 3, 4, 5];

var groups = items |> groupBy((e) => ...);
var evenCount = items |> countWhere((e) => ...);
var readOnly = items |> wrapWithUnmodifiableList();

Thoughts?

Here's the feature request.