-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
tuple decomposition declarator #10642
Comments
You mean like this? bool TryGet(Key key, out (int x, int y)) {
x = 123;
y = 456;
return true;
} |
Almost. With this grammar (type followed by declarator_id), it would be like this bool TryGet(Key key, out (int, int) (x, y)) {
x = 123;
y = 456;
return true;
} |
Shouldn't it be? bool TryGet(Key key, out (int x, int y) t) {
t.x = 123;
t.y = 456;
return true;
} as the out parameter is a tuple? |
@AdamSpeight2008 No, that is not a use of the feature under discussion here. That is just an ordinary parameter that has a tuple type, and what you wrote will work whether or not this feature request is done. To make it a use of the feature described here, you'd write bool TryGet(Key key, out (int x, int y) (x, y)) {
x = 123;
y = 456;
return true;
} |
I don't think introducing yet another decomposition syntax would be a good idea. As for tuple pattern verbosity we can use an identifier pattern (from Swift) which would also work in positional patterns, let (x, y) = (1, 2);
let case (var x, var y) = (1, 2);
let Point(x, y) = point;
let case Point(var x, var y) = point;
switch(o) {
case (var x, var y):
case let (x, y):
case Point(var x, var y):
case let Point(x, y):
}
// perhaps only a complete pattern may be used here
// or we can just `continue` when it doesn't match
foreach(let (x, y) in list)
// also, only complete patterns
TryGet(key, out let (x, y));
I think the only use case of a tuple deconstruction in |
@gafter How about with lambdas? var list = new List<(int, string)>() {
(123, "Hello"), (456, "World")
};
list.ForEach(((id, name)) => {
Console.WriteLine($"{id}: {name}");
}); Might be weird with the parenthesis, especially in the above case where the delegate accepts a single parameter and the parenthesis could normally be omitted, but doing so would make it ambiguous if there was an overload accepting a delegate with two parameters. |
@HaloFour I would really like to see this for all complete patterns: list.Select((let (var id, *)) => id);
// single parameter case
list.Select(let (var id, *) => id);
// or with Scala syntax
list.Select(case (var id, *) => id); However list.Select(t => t case (var id, *): id); What I don't understand is why there is a need for another decomposition syntax when we have patterns for just this purpose? |
@alrz This doesn't have much to do with patterns. We are not considering pattern-matching forms as part of method or lambda parameter specifications. |
@HaloFour I've updated the syntax to include support for implicit lambda parameters. |
My suggestion was based on other languages with pattern matching and tuples like F#, Scala, Swift, etc. They don't have a separate syntax for tuple decomposition, and they do allow patterns in lambda expressions or foreach loops, for example. |
I like |
@bondsbw I think the real advantage of this beyond |
So we'd have identifier-pattern like |
@gafter Right now we require a trailing identifier in type-pattern so it can't be just |
|
I prefer if we "borrowed" the |
@aluanhaddad I don't mind type test patterns, I just wanted to point out other languages do have an additional token for it because an identifier alone most certainly will be ambiguous. @AdamSpeight2008 Using |
Is it possible to use tuple declarators in LINQ var q =
from item in tuples
let (x, y) = item
select x + y; I'd like to know if all of the mentioned syntaxes will be available in C# 7.0, or just a portion of it? |
@alrz No. What is implemented in Roslyn now is all that is likely to be part of C# 7, with the possible addition of wildcard |
Closing, as the syntax model for deconstruction is not settled. |
This feature would allow multiple names to be declared wherever a single identifier declares a variable today, and the type is statically known to be a tuple type. Those individual identifiers would refer to the members of the (anonymous) underlying tuple variable.
For example, if a method returns a tuple
then one could call this method, and receive the results into an anonymous local variable, whose elements can be referred to by simple names:
one can think of
var
representing the type(int, int)
in this example, and the declaration is of an anonymous local variable of that type, whose members are accessible asx
andy
. This is similar to the mechanism of transparent identifiers in the specification of the Linq expression forms.Syntactically, this would be specified by introducing a declarator_id to be used in places that an identifier appears currently to define a variable.
Additional contexts include a number of query clauses.
This feature interacts with the
out var
feature, enabling one to receive a tuple produced in anout
parameter into a set of separate names for the tuple elements:For example a method declared like this
can be used like this
This might prove useful, for example, in extracting values from a dictionary whose
TValue
is a tuple.Open question: should this syntax be applicable for declaring method parameters?
@MadsTorgersen @VSadov @jcouv
The text was updated successfully, but these errors were encountered: