Skip to content

Instantly share code, notes, and snippets.

@svick
Last active March 29, 2018 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svick/1c321693f32078db9a002d064db77410 to your computer and use it in GitHub Desktop.
Save svick/1c321693f32078db9a002d064db77410 to your computer and use it in GitHub Desktop.

Expression variables in query expressions (version 3)

An expression variable is considered to be a promoted expression variable, when it's declared in the expression of a second or subsequent from clause, a let clause or a where clause and it's also referenced in one or more following clauses of the same query (but not across an into clause). Such expression variables are promoted into range variables.

Expression variables are allowed in all query clauses, but they affect how the query is translated only if they are promoted expression variables.

Translation

For an expression e with one or more promoted expression variables v1, ..., vn, its expanded form ee is the anonymous object creation expression fragment eo = e, v1, ... vn, where eo is a compiler generated identifier that is invisible and inaccessible, except when mentioned in this section.

The translation for clauses with one or more promoted expression variables is modified as follows:

A query expression with a second from clause

from x1 in e1
from x2 in e2
...

where e2 contains promoted expression variables is translated into

from * in ( e1 ) . Select ( x1 => new { x1, e2e } )
from x2 in e2o
...

A query expression with a let clause

from x in e
let y = f
...

where f contains promoted expression variables v1, ..., vn is translated into

from * in ( e ) . Select ( x => new { x , y = f, v1, ..., vn } )
...

A query expression with a where clause

from x in e
where f
...

where the type of f is bool and f also contains promoted expression variables v1, ..., vn is translated into

from * in ( e ) .
Select ( x => f ? new { x, v1, ..., vn } : null ) .
Where ( t => t != null )
...

Here t is a compiler generated identifier that is otherwise invisible and inaccessible.

A query expression with a where clause

from x in e
where f
...

where the type of f is not bool and f contains promoted expression variables is translated into

from * in ( e ) . Select ( x => new { x, fe } )
where fo
...

Notes

  1. The where clause has different translation when the type of its expression is bool. This is because the translation used for bool might not be applicable for other types.

Open questions

  1. This specification allows queries like from o in x where o is Foo foo select foo. Is that the right way to do it?
  2. The trick of using null to represent false result is weird, especially for a specification. Is there a better way to do this?
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment