dart-lang / dart-lang/language
loop expressions / collection-for alternative
- 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
Assessment
This issue has not been assessed yet.