Replies: 47 comments 5 replies
-
|
I agree that: Func<(int, int), int> f2 = ((a, b)) => a + b;should work already. This is a C# 7 bug in my view. However, I also agree that it would be good to have implicit deconstruction of tuples to parameter lists as an added bonus, as the need to use |
Beta Was this translation helpful? Give feedback.
-
|
IMO, this should work in the near future, but not now. This may be part of Pattern Matching in the 7.X milestone. var t = (1, 2);
if (t is (int a, int b)) // does not work today, but will work in 7.X
{
}
switch (t)
{
case (int a, int b): // does not work today, but will work in 7.X
break;
}
Func<(int, int), int> f = ((a, b)) => a + b; // does not work today |
Beta Was this translation helpful? Give feedback.
-
|
I would agree only on
But I don't agree with implicit deconstruction. In the future might be able to do anonymous function so we should always explicit. Should always avoid ambiguous syntax |
Beta Was this translation helpful? Give feedback.
-
|
I just stumbled about this limitation as well (the second case, but I agree with all) |
Beta Was this translation helpful? Give feedback.
-
|
Some of the explicitly mentioned LINQ-based examples would be ambiguous. Those LINQ methods have overloads which take delegates that accept two parameters. If you could deconstruct a tuple in the lambda parameters without a special syntax it wouldn't be possible for the compiler to disambiguate between |
Beta Was this translation helpful? Give feedback.
-
|
Great suggestion, but Kudos to @HaloFour for identifying the problem with the proposed syntax. I see that this is kept open as a proposal, but was a new issue opened for the bug with the case below?
|
Beta Was this translation helpful? Give feedback.
-
|
For reference, linking to LDM notes: https://github.com/dotnet/csharplang/blob/master/meetings/2017/LDM-2017-03-15.md#deconstruction-in-lambda-parameters |
Beta Was this translation helpful? Give feedback.
-
|
I want to point out the relationship of this proposal to another proposal (splatting).
|
Beta Was this translation helpful? Give feedback.
-
|
@jcouv To have lambda be a one line return without var point3s = new[] { (0,0,0),(1,1,1) }
var point2s = point3s.Select(((x,y,z)) => (x,y)); |
Beta Was this translation helpful? Give feedback.
-
|
This should be implemented for lambdas and methods. Thanks for writing up the proposal. I would like to point out that the OP has incorrect/inconsistent syntax for the case of methods. OP wrote: void Do((int x, int y), string name)
{
// use here x, y, and name
}However, this shouldn't compile because void Do((int x, int y) (x, y), string name) { }
void Do((int, int) (x, y), string name) { } |
Beta Was this translation helpful? Give feedback.
-
Just curious: what would the actual parameter name end up being, for older compilers? |
Beta Was this translation helpful? Give feedback.
-
|
Good point, I hadn't considered that. It's actually not just older compilers that are affected: you need to be able to use named arguments to pass a tuple-typed argument to a method with optional parameters. My proposal here would be that the syntax could be extended to accommodate an extra parameter name, for example: public void Method((int, int) (x, y) point) { }but this would be optional; if such an extra parameter name is not provided, the compiler would generate one by combining the names from the deconstruction syntax. For example, |
Beta Was this translation helpful? Give feedback.
-
|
Why this feature not be championed for C# 8.0 I wonder |
Beta Was this translation helpful? Give feedback.
-
|
I have to admit I expected it to work. I typed and found out it didn't work. |
Beta Was this translation helpful? Give feedback.
-
|
@jhudsoncedaron Because that was the actual syntax for normal lambda Even this feature work it should be .Select(((a,b)) => { /* 4 lines of code here */ return something; })I think we should deprecate the no parentheses syntax for lambda |
Beta Was this translation helpful? Give feedback.
-
Thanks for pointing that out, @CyrusNajmabadi 👍 (Unfortunately for me it was more like: "... search the web and read Stack Overflow and GitHub tickets for half an hour, and then write: ..." 😄) |
Beta Was this translation helpful? Give feedback.
-
|
The solution @CyrusNajmabadi proposed works, but if you move the naming over to where the tuple is constructed, it's quite a bit nicer (particularly if you're returning |
Beta Was this translation helpful? Give feedback.
-
|
Thanks, @kswoll . In my case the tuple returned generically from an API that can't give the fields meaningful names (only the consumer of the API knows what each field in the tuple represents), but the tip is appreciated! |
Beta Was this translation helpful? Give feedback.
-
|
My case was similar to nbumhardt's case. The tuple appeared in template parameter expansion. |
Beta Was this translation helpful? Give feedback.
-
|
Sadly this feature was so stale |
Beta Was this translation helpful? Give feedback.
-
|
Will it be implemented in after-covid era? |
Beta Was this translation helpful? Give feedback.
-
|
After we got named ValueTuple elements I stopped caring. |
Beta Was this translation helpful? Give feedback.
-
|
If anyone would champion this in the future can it moved back to issue board? |
Beta Was this translation helpful? Give feedback.
-
|
Another workaround is to use switch expression added to C# 8: var r = Enumerable
.Range(1, 10)
.Select(i => (i + 1, i * i))
.Where(_ => _ switch { var (a, b) => 2 * a < b })
.OrderBy(_ => _ switch { var (a, b) => b })
.Last();and Func<(int, int), int> f2 = _ => _ switch { var (a, b) => a + b }; |
Beta Was this translation helpful? Give feedback.
-
How about I would add I think none of these should contribute to overload resolution or type inference though - deconstruction conversion would apply as the last step and may fail. |
Beta Was this translation helpful? Give feedback.
-
|
I was looking for that. Wrote this extension to make that possible. But I would appreciate if this would be standard: public static IEnumerable<TResult> Select<TItem1, TItem2, TResult>(this IEnumerable<(TItem1, TItem2)> source, Func<TItem1, TItem2, TResult> selector)
{
return source.Select(s => selector(s.Item1, s.Item2));
} |
Beta Was this translation helpful? Give feedback.
-
|
I will champion this. |
Beta Was this translation helpful? Give feedback.
-
|
@CyrusNajmabadi Just want to surface this to your attention again. I use higher order functions and tuples very frequently, so this syntax (only basic tuple deconstruction in lambda parameter list) is by far my most desired feature. I find myself being shaken out of my flow and writing boilerplate like this constantly. Given C#'s mission of reducing boilerplate, how simple and intuitive of a language change this would be, and how cohesive it is with recent changes to the language, I would ask that we continue to advocate for this proposal 🙏 Thanks for all ya'll do! C# continues to be the best language on the market for those that rate it on its objective merits. P.S. for what it's worth, I think we should NOT add support for as it is ambiguous syntax, doesn't make the code more clear, and creates "magic" to confuse new programmers. |
Beta Was this translation helpful? Give feedback.
-
|
There's now a proposal at #9848 and @CyrusNajmabadi and I will bring this to an upcoming LDM as the schedule allows! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
A lambda that accepts a (single) tuple as argument can only be defined with the tuple as a single argument and not by the tuples items. I’d like to see that the tuple deconstruction also works in the argument list of lambdas, as shown in the following examples:
Note that in the last line the parenthesis belong to the tuple deconstruction and not the lambda argument list.
This feature would be handy for Linq or Rx method chaining:
Of course the given calculation doesn’t make much sense, but I guess you get the idea. That’s why I'd like to see this feature. But to be consequent, more complex constructs would become possible:
And probably that should also be extended to methods (and delegates):
Beta Was this translation helpful? Give feedback.
All reactions