Roslyn: Proposal: multiple variables declared in a 'let' query clause

Created on 20 Sep 2016  Â·  4Comments  Â·  Source: dotnet/roslyn

I propose to allow multiple variables in a query expression's let clause.

The specification would be changed to support this as follows:

A query expression with a let clause

from x in e
let y = f, z = g, …
…

is translated into

from * in ( e ) . Select ( x => new { x , y = f, z = g, … } )

this would facilitate the use of out var arguments in query expressions with no additional machinery:

from x in e
select y = M(out var z0), z = z0

It may also have some synergy with tuples and pattern-matching.

/cc @jcouv @VSadov @AlekseyTs @MadsTorgersen

Area-Language Design Language-C# New Language Feature - Out Variable Declaration New Language Feature - Tuples

Most helpful comment

Please also consider the select+filter scenario of using pattern matching with LINQ which I think will become and incredibly common use case.

Would be nice if out variables in LINQ clauses could automatically be promoted to range variables. I know that would drastically change how the LINQ clauses are translated.

IEnumerable<string> words = ...;
var numeric = from word in words
    where int.TryParse(word, out int number)
    select number;

// translated into

var number = words.Select(word => {
        int number;
        bool success = int.TryParse(word, out number);
        return (word, success, number);
    })
    .Where(tuple => tuple.Item2)
    .Select(tuple => tuple.Item3);

All 4 comments

Please also consider the select+filter scenario of using pattern matching with LINQ which I think will become and incredibly common use case.

Would be nice if out variables in LINQ clauses could automatically be promoted to range variables. I know that would drastically change how the LINQ clauses are translated.

IEnumerable<string> words = ...;
var numeric = from word in words
    where int.TryParse(word, out int number)
    select number;

// translated into

var number = words.Select(word => {
        int number;
        bool success = int.TryParse(word, out number);
        return (word, success, number);
    })
    .Where(tuple => tuple.Item2)
    .Select(tuple => tuple.Item3);

I would like to point out that the proposed translation looks inconsistent with VB translation. In VB, comma inside Let clause is causes an extra Select call and all range variables declared in the Let clause prior to the comma are in scope after the comma. I.e. Let a = <expr1>, b = <expr2> is equivalent to Let a = <expr1> Let b = <expr2> and a is in scope in expr2.

We considered this yesterday in the LDM and we believe we are more likely to support

A query expression with a let clause

from x in e
let (y, z) = e2
…

is translated into

from * in ( e ) . Select ( x => new { x , y = (var (y, z) = e2).Item1, z = z } )

/cc @dotnet/ldm

Was this page helpful?
0 / 5 - 0 ratings