dart-lang / dart-lang/language

loop expressions / collection-for alternative

Open
#4,142 11 comments 0 reactions 0 assignees View on GitHub
feature
Dominant language
TeX
Stars
2.9k
Forks
239
Avg merge
2d 18h
Merged PRs (30d)
14

Description

### Motivation / Inspiration
This proposal is proposes a sort of alternative / anti-thesis to the current collection-for we have, it would allow the collection-for to be more powerful and expressive, and it would solve almost all the proposals asking for extending the collection-for. The inspiration / motivation comes from #4139. I've also searched for similar proposals, because i was sure there had to be one already, but there was none exactly to my liking. The most similar proposal i found is #1633. If there is some proposal i've overlooked, please point me to it.

### Proposal
The proposal is straightforward. I propose allowing `for` / `while` to be used as expressions. The return value for the loop expression would be `Iterable` / `Stream`, which would be lazily evaluated. The values would be passed to the output iterable with a `yield` keyword. Basically, you can think of it as a modification on proposal #1633, which makes it imo easier and more compact to use.
```dart
// example from #4139
// iter -> Iterable = inferred
var iter = for(final item in [1,2,3]){
if(item < 2) continue;
doSomething();
doSomethingElse();
yield item + 3;
}

// iter -> Iterable = explicitly typed
var iter = for(final item in [1,2,3]) yield item*2;

// stream -> Stream
var stream = for(final item in [1,2,3]) async {
await foo;
yield item * 2;
}

// embedded into list / list comprehension
final list = [
firstElement,
... for(final item in [1,2,3]){
if(item < 2) continue;
doSomething();
doSomethingElse();
yield item + 3;
},
lastElement,
];
```
This allows it to be used outside the collections, and allows for easier representation of complex operation on some list.
### `collection-for` and `for as expressions` interaction
These two paradigms don't mix well / use the same syntax which makes them ambiguous, which is which. That is a big problem, of which i'm aware of. This proposal is more of an antitheses to the collection-for and as such it is a different look at how to do list comprehention. One way to fix the ambiguity is to assume all `for` is used as `expression` and just spread the resulting iterable. This could be easily done with a migration script.

```dart
// before migration script
final list = [
firstElement,
for(final item in [1,2,3]) item + 3,
lastElement,
];

// after migration script
final list = [
firstElement,
... for(final item in [1,2,3]) yield item + 3,
lastElement,
];

// possibly the yield keyword could be removed if there is only one statement
```

### Other
I personally think that that `for as expressions` is a much better way to do list comprehention compared to the python-style collection-for we have today. My main argument for this is that `for as expressions` allow for a lot more flexibility than `collection-for` without using any of the usefulness (they can also be easily embedded into collections by spreading).

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.