Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add yield to collection for #4024

Open
feinstein opened this issue Aug 9, 2024 · 3 comments
Open

Add yield to collection for #4024

feinstein opened this issue Aug 9, 2024 · 3 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@feinstein
Copy link

feinstein commented Aug 9, 2024

I constantly feel that collection for is almost there, but not there. It allows some cool syntax for simple cases, but constantly I need to add just a few more steps, like getting data from an async call, then deciding if I should add it to the list or not.

With the current syntax, we can use {}, so we are restricted to simple 1 line cases.

This made me think that we might (I am not aware of the complexity) combine generators and collection if (at least in the syntax, merging their functionality might make the code more complex or with worse performance), to allow us something like:

Future<List<String>> getStrings() async {
  return [
    for (final myInt in myInts) {
      final myString = await getMyData()
      if (myString != null) {
        yield myString; // This will signal to the collection for that we are producing a new item.
      }
    }
  ];
}

With the yield keyword we could leverage collection if to spread across several lines.

I apologize in advance if I am missing something, I bet I am, as language features are always tricky.

@feinstein feinstein added the feature Proposed language feature that solves one or more problems label Aug 9, 2024
@julemand101
Copy link

I think one detail missing here is that using { ... } is problematic since this can mean a Map or Set depending on situation when used in defining a list using [ ... ]. So I think there a high chance here for it to making it confusing or not possible to tell the difference if you mean a code block or you mean to define a Set.

@Mike278
Copy link

Mike278 commented Aug 9, 2024

Pattern matching in if elements has mostly solved this for me:

Future<List<String>> getStrings() async {
  return [
    for (final myInt in myInts) 
      if (await getMyData() case final myString?) 
        myString
  ];
}

Though sometimes I do find myself wanting to use a switch expression instead but it's a bit clumsy since a switch expression can't evaluate to "nothing".

@lrhn
Copy link
Member

lrhn commented Aug 9, 2024

I also think that the binding ability of for and if+case makes up for most of the reasons I've had for needing imperative code blocks. If that's not enough, a helper function, maybe with a spread on the result, usually is.

And in this case, the null-aware element (#323) would be a slam-dunk:

async => [for (final myInt in myInts) ?await getMyData(myInt)];

Or you might want parallelism:

=> myInts.map(getMyData).wait;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

4 participants