I would like to see C#'s LINQ get an update. It seems to have been left to rot since Eric Meijer left the team. It doesn't even support the new values tuples where it's been fitted to every other part of the language:
from (x,y) in Some((1,2)) // (x,y) will error
select x + y;
The from x in y, let x = y, where x, select x, and, join x in y on a equals b, could and should be extended. Even better would be to allow custom operators like F#'s computation expressions.The LINQ to SQL stuff annoys me, because while it works, it's a painful disaster to implement yourself against your own data stores. Believe me, I've tried.
Honestly, if you've seen what LINQ compiles to, it looks an awful lot like a Java 8 Stream.
Using Wikipedia's example of LINQ translation (https://en.wikipedia.org/wiki/Language_Integrated_Query#Lang...):
Written LINQ is:
var results = from c in SomeCollection
where c.SomeProperty < 10
select new {c.SomeProperty, c.OtherProperty};
It compiles to: var results =
SomeCollection
.Where(c => c.SomeProperty < 10)
.Select(c => new {c.SomeProperty, c.OtherProperty});
And in Java 8: Stream<> results = someCollection.stream()
.filter(c -> c.getSomeProperty() < 10)
.map(c -> new AbstractMap.SimpleEntry<>(c.getSomeProperty(), c.getOtherProperty()));
(of course, iterating over them is different; you just use a for loop in C#, but in Java you have to either use .forEach() or .collect() to a collection and then for over that)I think Streams have more LINQ in them than most people think.
Disclaimer: it's been about a year since I've written Java 8, and this is off the top of my head (and the last time I used it, my employer's codebase had a class for pairs that was better than just SimpleEntry), so the code could be wrong.
Edit: and just for completeness... the same in Python generator expressions:
results = ((c.some_property, c.other_property)
for c in some_collection
if c.some_property < 10)
Not very LINQ-like, but it serves the same purpose.It's just more readable, and turns it into an object pipeline/functional programming style instead. The Java 8 streams were pretty much directly taken from LINQ and given their traditional functional names.
That was my point. I was disagreeing with olmo's suggestion that Java "systematically ignored" LINQ.
What's your source for this claim? Because anecdotally I don't see that at all.
Most uses of where/order/select in C# I'm pretty sure is linq to objects, not sql. I very rarely see the linq proper form in any C# code neither in OSS or in my dat job.
Closest thing we have to real data, but it's been my experience in OSS and in professional life.
I also don't use LINQ to SQL at all. It's all on in-memory stuff. I pretty much never write code like this:
var result = new List<string>();
foreach (var item in input)
{
result.Add(item.Value);
}
return result;
instead, using LINQ: return items.Select(x => x.Value);
The real power comes when you start mixing conditions: return items
.Where(x => IsValidKey(x.Key))
.Select(x => x.Value);
Or doing quick checks: if (items.Any(x => x == null || x.SomeValue == null))
throw new InvalidArgumentException(nameof(items));if(items.Any(x => x?.SomeValue == null))
var results = from a in x
from b in y
from c in z
select a * b * c;
Is very much more attractive than: var results = x.SelectMany(a => y.SelectMany(b => z.Select(c => a * b * c)));
If you use LINQ for more than just SQL queries (for monadic types like Option, Either, etc.) then these types of expression are commonplace. I'd certainly rather use C#'s LINQ grammar over its fluent API. dogs
.Select(d => d.Id)
.Where(d => d.Age > 3)
.Skip(4)
.Take(2)
would be considered just as much "linq" by most c# devs even though this isn't the query language integrated - simply because it's the same exact thing as the regular linq code.I too find the "real" linq form mostly distracting.
Most of it boils down to plain old functional map/fold/filter/zip constructs under different names.
map/filter/reduce are just basic functional programming elements.
This allows you to compose linq expressions without computing intermediate results.
Streams bear a pretty strong resemblance to translated LINQ.