Skip to content

tuple decomposition declarator #10642

@gafter

Description

@gafter

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

    (int, int) M() => (1, 2);

then one could call this method, and receive the results into an anonymous local variable, whose elements can be referred to by simple names:

    var (x, y) = M();
    // following code can use x and y

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 as x and y. 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.

declarator_id
    : identifier
    | '(' declarator_id ',' declarator_id_list ')'
    ;

declarator_id_list
    : declarator_id
    | declarator_id_list ',' declarator_id
    ;

local_variable_declarator
    : declarator_id
    | declarator_id '=' local_variable_initializer
    ;

foreach_statement
    : 'foreach' '(' local_variable_type declarator_id 'in' expression ')' embedded_statement
    ;

variable_declarator
    : declarator_id
    | declarator_id '=' variable_initializer
    ;

implicit_anonymous_function_signature
    : '(' implicit_anonymous_function_parameter_list? ')'
    | identifier
    ;

implicit_anonymous_function_parameter_list
    : declarator_id
    | implicit_anonymous_function_parameter_list ',' declarator_id
    ;

explicit_anonymous_function_parameter
    : anonymous_function_parameter_modifier? type declarator_id
    ;

Additional contexts include a number of query clauses.

This feature interacts with the out var feature, enabling one to receive a tuple produced in an out parameter into a set of separate names for the tuple elements:

argument_value
    : 'out' type declarator_id
    | ...
    ;

For example a method declared like this

    bool TryGet(Key key, out (int, int) value) { ... }

can be used like this

    if (TryGet(key, out var (x, y))
    {
        // x and y can be used here
    }

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions