Linq "into" and "let" equally???

  • Thread starter Thread starter Alexander Vasilevsky
  • Start date Start date
Linq "into" and "let" equally???

Do you mean "do they do the same thing"? If so, do you mean
"select ... into" rather than "group ... into"?

I'll assume you mean "select ... into". They're not quite the same.
When you do "select ... into" you have a *single* range variable at
that point; any previous range variables are gone, basically.

If you do "let" then it just introduces a *new* range variable. So,
for instance, you could do:

var query = from x in Enumerable.Range(0, 10)
let y = x*2
select x+y;

But if you do:

var query = from x in Enumerable.Range(0, 10)
select x*2 into y
select x+y;

it will fail, because at the "x+y" stage "x" is no longer available.

(I haven't tried the above code yet - I'm about to do so when I've
installed 3.5 onto my laptop.)

Jon
 
Jon said:
Do you mean "do they do the same thing"? If so, do you mean
"select ... into" rather than "group ... into"?

I'll assume you mean "select ... into". They're not quite the same.
When you do "select ... into" you have a single range variable at
that point; any previous range variables are gone, basically.

If you do "let" then it just introduces a new range variable. So,
for instance, you could do:

var query = from x in Enumerable.Range(0, 10)
let y = x*2
select x+y;

But if you do:

var query = from x in Enumerable.Range(0, 10)
select x*2 into y
select x+y;

With queries like that, I always wonder why on earth would anyone want
to use that construct in that way...

I mean: why would anyone use select <expression> into <var> ? Or am I
the only one who finds the painful mix between set oriented
functionality and imperative programming within linq a bit 'odd' ?

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
With queries like that, I always wonder why on earth would anyone want
to use that construct in that way...

I mean: why would anyone use select <expression> into <var> ? Or am I
the only one who finds the painful mix between set oriented
functionality and imperative programming within linq a bit 'odd' ?

It's a good indicator that the only thing you care about from the
previous query is the actual result of the select - no intermediate
stuff needs to be propagated. (This could also make things a bit more
efficient in some cases, although that's rarely an issue.)

I'd personally write it as two queries:

var firstQuery = from x in source where blah select foo;
var secondQuery = from bar in firstQuery where ...;

which is basically the same thing, but a bit clearer IMO. There's room
for personal preference though :)

Jon
 
Alexander said:
Why painful?

because it keeps people in an imperative mindset, which means that
they can't use the set-oriented functionality in full potential.
Perfect examples are people who write long pieces of SQL with cursors
because they don't understand how set-oriented languages work.

FB
"Frans Bouma [C# MVP]" <[email protected]>
???????/???????? ? ???????? ?????????:
With queries like that, I always wonder why on earth would anyone
want to use that construct in that way...

I mean: why would anyone use select <expression> into <var> ? Or am I
the only one who finds the painful mix between set oriented
functionality and imperative programming within linq a bit 'odd' ?


--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
Frans Bouma said:
because it keeps people in an imperative mindset, which means that
they can't use the set-oriented functionality in full potential.
Perfect examples are people who write long pieces of SQL with cursors
because they don't understand how set-oriented languages work.

I don't see how it keeps people in an imperative mindset. It allows
them to express that the sequence which is the result of the "select"
is all they need for the next part of their query.

LINQ isn't actually set-oriented - it's sequence-oriented, a pipeline.
It may be convenient to think in terms of sets when writing LINQ to
SQL, but LINQ to Objects should *definitely* be considered in terms of
sequences.
 
Jon said:
I don't see how it keeps people in an imperative mindset. It allows
them to express that the sequence which is the result of the "select"
is all they need for the next part of their query.

LINQ isn't actually set-oriented - it's sequence-oriented, a
pipeline. It may be convenient to think in terms of sets when
writing LINQ to SQL, but LINQ to Objects should definitely be
considered in terms of sequences.

A query which is executed on a db, will end up as a set-oriented
statement. If you write your query as imperative as possible, you WILL
probably have a slow query. A query written to be executed on a DB
should be written with set operations in mind, otherwise you will end
up sooner or later at the wrong end of the DBA-developer conversation
where you need to optimize the query to make it performing properly but
you don't know how.

FB


--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
Frans Bouma said:
A query which is executed on a db, will end up as a set-oriented
statement.

Yes. And a query which is executed in-process will end up as a
sequence-oriented statement.
If you write your query as imperative as possible, you WILL
probably have a slow query. A query written to be executed on a DB
should be written with set operations in mind, otherwise you will end
up sooner or later at the wrong end of the DBA-developer conversation
where you need to optimize the query to make it performing properly but
you don't know how.

It depends on what you mean by "as imperative as possible". I don't see
"let" as being particularly imperative - you could regard it as
assigning an alias. The test queries I've done against LINQ to SQL
(which aren't many, admittedly) look fine to me.
 
Jon said:
It depends on what you mean by "as imperative as possible". I don't
see "let" as being particularly imperative - you could regard it as
assigning an alias. The test queries I've done against LINQ to SQL
(which aren't many, admittedly) look fine to me.

Example: (I used 'from' here to make it more clear, I also could have
used let, it would result in a SelectMany as well)

var q = from c in nw.Customers
join o in nw.Orders on c.CustomerID equals o.CustomerID into co
from x in co.DefaultIfEmpty()
from y in co.DefaultIfEmpty()
where x.OrderID == null
select c;

the thing is that the right side of the group join here is placed
twice into the query, because two variables are pulled from it. This is
strange, as co represents a set, so referring to it suggests the set
doesn't change, and you can just refer to it as a variable.

The above query is a bit meaningless, but what if the second
DefaultIfEmpty call is replaced by:
let y = co.Count()

Is it then still clear that it results in another subquery? After all,
'co' already exists, according to MSDN, co is the set of sequences of
orders, one sequence for every customer in the above query. However,
that suggests that that set of sequences is a set to use as a resource,
but that's not the case: every time the set 'co' is referred to, a new
subquery or join will be added to the SQL output. This doesn't match
with the imperative nature of using data stored in a variable.

FB

--
------------------------------------------------------------------------
Lead developer of LLBLGen Pro, the productive O/R mapper for .NET
LLBLGen Pro website: http://www.llblgen.com
My .NET blog: http://weblogs.asp.net/fbouma
Microsoft MVP (C#)
------------------------------------------------------------------------
 
Example: (I used 'from' here to make it more clear, I also could have
used let, it would result in a SelectMany as well)

No, "let" doesn't result in SelectMany - it results in another Select.

From the spec:

"A query expression with a let clause
from x in e
let y = f
....
is translated into
from * in ( e ) . Select ( x => new { x , y = f } )"

Does that change your opinion of it?

Jon
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top