[Proposal] yield expression #3325
Replies: 25 comments
-
I think local functions are a reasonable solution to the first point. I think if this were done, it also ought to be done for async blocks. Both scala and Rust support these. |
Beta Was this translation helpful? Give feedback.
-
@YairHalberstadt , local functions resolve the problem to the first point, but becomes a code smell, specially when you need to declare more than one sequence; public IEnumerable<string> Names => _names();
public IEnumerable<int> Ids => _ids();
IEnumerable<string> _names()
{
yield return "bob";
yield return "tom";
}
IEnumerable<int> _ids()
{
yield return 1;
yield return 2;
} Could be more clean like public IEnumerable<string> Names => yield
{
return "bob";
return "tom";
}
public IEnumerable<int> Ids => yield
{
return 1;
return 2;
} This feature propose a clean way of doing things, much like switch expression feature do. |
Beta Was this translation helpful? Give feedback.
-
@RUSshy what do you meant by "support high order functions directly"? C# supports high order functions with delegates, LINQ was done on top of this. Can you give us any example? |
Beta Was this translation helpful? Give feedback.
-
@RUSshy if I understood right, your example works the same way I proposed for yield expression. Inside both |
Beta Was this translation helpful? Give feedback.
-
Kotlin is a very different language, though. They have continuation primitives and suspendable functions which lend to constructing different kinds of coroutines, plus a syntax that lends itself to constructing DSLs. IMO if lambdas could be iterators in C# I think that would make it easier to solve this issue. A helper function like |
Beta Was this translation helpful? Give feedback.
-
@HaloFour lambdas returning iterators would be nice too, but I suppose it is harder to be implemented, as you said, would be effort to improve 1) lambdas and 2) generic inference as well. yield expression are closer of syntax sugar for methods. |
Beta Was this translation helpful? Give feedback.
-
I think we actually prototyped it one time, and it was fine. It's really more about it just not being compelling enough to add the complexity to the language. All the examples just never seem worth it, and the existing workarounds seem totally sufficient for what seems to be a 1% of a 1% case. |
Beta Was this translation helpful? Give feedback.
-
I think the generic inference issue would have to be solved in both cases, at least if you wanted to assign this inline iterator to a |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I supposed that for the inline iterator the var people_eager = new[]
{
new { Name = "bob", Age = 12 },
new { Name = "tom", Age = 24 },
}; what does not look syntactically so different of what is being proposed var people_lazy = yield
{
return new { Name = "bob", Age = 12 };
return new { Name = "tom", Age = 24 };
}; however about var simplestAction = () => { Console.WriteLine("hello world"); }; |
Beta Was this translation helpful? Give feedback.
-
I agree with @HaloFour that lambda iterator, allow using And it could insert logic with var iter = Enumerable.Lambda(() => {
yield return "bob";
if(condition0)
yield return "alice";
yield return "tom";
}); |
Beta Was this translation helpful? Give feedback.
-
@Thaina use One possible advantage, is that "yield expression" are closest of a readonly iterator method, that is, would also allow declare variables, loops, conditions, capture outer variables, etc, but without generate any side-effect, like a true expression. Following code would be valid in my feature initial proposal. public IEnumerable<string> Names => yield
{
return "bob";
if(condition0)
return "alice";
return "tom";
} |
Beta Was this translation helpful? Give feedback.
-
@leandromoh In that aspect I have been create #249 about anonymous function expression in general. I think we should have expression to create a block of function that could For the shorthand property I still prefer public IEnumerable<string> Names => {
yield return "bob";
if(condition0)
yield return "alice";
yield return "tom";
} Even we have |
Beta Was this translation helpful? Give feedback.
-
@Thaina I agree that |
Beta Was this translation helpful? Give feedback.
-
This would prevent us from ever being able to have an expression that starts with Given how niche |
Beta Was this translation helpful? Give feedback.
-
@CyrusNajmabadi As for me I think It felt niche because we have existing alternative. But if it has been implemented it might be used to replace the alternative code we have been using so far. In the same way as |
Beta Was this translation helpful? Give feedback.
-
@Thaina I agree with your points. Return a new array every time in a get expression is expensive, and as you said this feature would allow us to have complex logic too. |
Beta Was this translation helpful? Give feedback.
-
That doesn't make it not niche.
Yes.
Yes, i get that. But that doesn't make it not-niche.
No one is proposing htat. You can have iterators today. you justhave to name them with a method or local function. The question is if it's needed for an even less verbose way of doing things. |
Beta Was this translation helpful? Give feedback.
-
Yes. Yield expression has the same purposes of switch expression, if I understood it properly. You always could create a method with a I am proposing to do the same thing with |
Beta Was this translation helpful? Give feedback.
-
Yes, i understand. :) Let me try to state things differently: https://docs.microsoft.com/en-us/archive/blogs/ericgu/minus-100-points It's not a question of "can we do this?" or "is this similar to something we've done?". It's a question of "is this valuable enough to do". I'm stating that this seems far to niche to warrant the work. |
Beta Was this translation helpful? Give feedback.
-
Expression blocks are another option to make this possible without new special syntax. |
Beta Was this translation helpful? Give feedback.
-
F# has that too. |
Beta Was this translation helpful? Give feedback.
-
@IllidanS4 the expression blocks proposal says "return, yield break, yield return are not allowed in the expression block statements." in its "Restrictions" section. |
Beta Was this translation helpful? Give feedback.
-
@leandromoh I presumed this restriction could be lifted, but that is based on the actual interpretation of the meaning of expression blocks. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Currently, the only way to create a lazy sequence with
yield return
is create a method (local or not). However sometimes things could be simpler. Instead of declare a method to use the lazy sequence it produces as a local variable or in a get expression of a property , we could create a "yield expression", in a similar way of switch expression feature.Instead of write this boilerplate code
We could write something like
This feature would also allow create sequences of anonymous values with lazy evaluation in an optimum way. Since the current obvious approach we need to specify the return type in the method signature, there is no way to return an anonymous with the benefits of static typing.
Usage with anonymous:
Like iterator methods, "yield expression" would also allow declare variables, loops, conditions, capture outer variables, etc, but without generate any side-effect (like a iterator method that is a readonly member)
Beta Was this translation helpful? Give feedback.
All reactions