Hacker News new | ask | show | jobs
by amyjess 3414 days ago
In the case of Python and Java, I think it's because generator expressions and Streams, respectively, accomplish much the same thing.

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.
3 comments

The thing you're missing is the way that LINQ creates an anonymous type, which is used to close over the values in the expression:

    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.
What you miss is that with LINQ you can extract the expression tree : https://msdn.microsoft.com/fr-fr/library/mt654263.aspx This is what is used to generate the SQL.
In the real world, MOST people are using the "it compiles to" version directly in the code. I certainly don't write the "from x in y select" version, except in the case of multiple hairy joins. Even those have become second nature at this point.

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.

> 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.

Ah okay, I misunderstood. Indeed.
> In the real world, MOST people are using the "it compiles to" version directly in the code

What's your source for this claim? Because anecdotally I don't see that at all.

Our codebase at work has hundreds if not thousands of LINQ queries, mostly using method syntax. I generally prefer it over query syntax except in a few cases, such when there's multiple joins or subqueries, or the when the statement is more than a few dozen lines. Occasionally a very complex LINQ statement requires using a `let` declaration which also is easier with query syntax. Luckily Resharper has an action to convert back and forth on the fly, so it's easy to use that to switch over when necessary.

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));
And now, with C#6 that last bit becomes:

if(items.Any(x => x?.SomeValue == null))

I think it depends on what the Linq to is. I find the sql like proper linq form only natural when databases are involved (and just barely).

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.

I never use the query syntax, or ever see it in any of the books or blogs I read, to the point that it threw me for a loop a little bit when I was studying for the C# certification exam, to see how emphasized it was. I learned that style long ago when I first started, but the fluent, extension method style is easier and less ugly, IMO, particularly when you start getting into more complex queries, or LINQ-to-SQL, where you end up wrapping your multi-line LINQ query in parentheses and materializing it by calling ToList() or ToDictionary() at the end.
https://blog.oz-code.com/analyzing-github-linq-usage-the-res...

Closest thing we have to real data, but it's been my experience in OSS and in professional life.