Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm having a discussion with a co-worker on Linq, I'll copy here:

Co-Worker: Lets be honest here. Linq syntax sucks. It's confusing and non-intuitive.

Me: oh come on, more confusing than T-SQL?

Co-Worker: uh, yes.

Me: it has the same basic parts, select, where, and from

Co-Worker: Linq, to me, is a bastardization of relational + OO. Co-Worker: Don't get me wrong - it's incredibly powerful, but they repurposed SQL to use agains object collections.

I'm of the opinion that using Linq + Lamda's is very powerful (he agrees), and also makes code easier to read (he disagrees on that point):

pickFiles = from f in pickFolder.GetFiles("*.txt")
where ValidAuditFileName.IsMatch(f.Name)
select f;

or

var existing = from s in ActiveRecordLinq.AsQueryable<ScannedEntity>()
where s.FileName == f.FullName && s.DocumentType != "Unknown"
select s;

or (VB code here)

   Dim notVerified = From image In images.AsParallel
     Group Join verifyFile In verifyFolder.GetFiles("*.vfy").AsParallel.Where(
      Function(v) v.Length > 0
      ).AsParallel
   On image.Name.Replace(image.Extension, ".vfy") Equals verifyFile.Name
     Into verifyList = Group
    From verify In verifyList.DefaultIfEmpty
    Where verify Is Nothing
    Select verify

To me this is clean and easy (at least easier than the alternatives) to read, what are your opinions on it?

share|improve this question
6  
Humans, in general, hate change. A large percent hate it so much that they actually fear it. –  Tony Dec 9 '10 at 16:05
7  
Let's face it... linq is just a dumbed down functional programming syntax added to C# and VB.Net. Bashing linq and lambda expressions is basically saying "FP sucks". That's what your co-worker is saying. I think that debate has been hashed out elsewhere. –  Scott Whitlock Dec 9 '10 at 16:12
27  
Does it bother anyone else that people tend to use the word "intuitive" when they really mean "familiar"? –  Larry Coleman Dec 9 '10 at 21:52
6  
Anyway, the C# team (including Eric Lippert) have gone out of their way to explain that Linq was not a porting of SQL, it was designed from the ground up like most other features. I would have to say that your co-worker is a Luddite. –  Aaronaught Dec 9 '10 at 23:34
13  
For what it's worth: I just had my wife (office administrator - next to zero practical programming experience) look at aaronaught's 3 examples and was able to decipher the intent of the linq and lambda examples far more easily than the traditional imperative example. –  Steve Evers Dec 10 '10 at 1:14
show 6 more comments

9 Answers

up vote 54 down vote accepted

I can't find the right post anymore, but Eric Lippert (and possibly several other softies) have opined on several occasions about how Linq is declarative, which, for several classes of problems, is far more intuitive than imperative syntax.

Linq enables you to write code that expresses the intent, not the mechanism.

You tell me which is easier to read. This:

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    List<Customer> results = new List<Customer>();
    foreach (Customer c in source)
    {
        if (c.FirstName == "Aaron")
        {
            results.Add(c);
        }
    }
    results.Sort(new LastNameComparer());
    return results;
}

class LastNameComparer : IComparer<Customer>
{
    public int Compare(Customer a, Customer b)
    {
        return x.LastName.CompareTo(b.LastName);
    }
}

Or this?

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    return from c in source
           where c.FirstName == "Aaron"
           orderby c.LastName
           select c;
}

Or even this?

IEnumerable<Customer> GetVipCustomers(IEnumerable<Customer> source)
{
    return source.Where(c => c.FirstName == "Aaron").OrderBy(c => c.LastName);
}

The first example is just a bunch of pointless boilerplate in order to obtain the simplest of results. Anybody who thinks that it is more readable than the Linq versions needs to have his head examined. Not only that, but the first one wastes memory. You can't even write it using yield return because of the sorting.

Your coworker can say what he wants; personally, I think Linq has improved my code readability immeasurably.

There's nothing "relational" about Linq either. It may have some superficial similarities to SQL but it does not attempt in any shape or form to implement relational calculus. It's just a bunch of extensions that make it easier to query and project sequences. "Query" does not mean "relational", and there are in fact several non-relational databases that use SQL-like syntax. Linq is purely object-oriented, it just happens to work with relational databases through frameworks such as Linq to SQL because of some expression tree voodoo and clever design from the C# team, making anonymous functions implicitly convertible to expression trees.

share|improve this answer
5  
+1 I love voodoo –  BlackICE Dec 10 '10 at 14:35
4  
+1 If you don't like LINQ its probably because "you ain't doing it right" :) –  Darknight Dec 13 '10 at 9:28
add comment

Co-Worker: Lets be honest here. Linq syntax sucks. It's confusing and non-intuitive.

You can't argue with that criticism. For your coworker, it sucks. We failed to design a syntax that, for them, was clear and intuitive. That's our failing, and you can pass on my apologies to your coworker. I am happy to take suggestions on how to make it better; what specifically does your coworker find confusing or unintuitive?

However, you can't please everyone. My personal opinion, and the opinion of most of the people I've talked to on the subject, is that the query comprehension syntax is much more clear than the equivalent imperative syntax. Clearly not everyone agrees, but fortunately we do not require consensus of all the millions of our customers when we do language design.

On the subject of what is "intuitive" though, I am reminded of the story of the English linguist who studied many different languages and finally concluded that English was the best of all languages because in English, the words come in the same order that you think them. Unlike French, where they're constantly saying things like "the dog white eats the meat red". How hard it must be for French people to think the words in the correct order and then have to say them in the French order! French is so unintuitive! It's amazing that the French manage to speak it. And German? where they think "the dog eats the meat" but then have to say "the dog the meat eats" !?! So unintuitive.

Often what is "intuitive" is merely a matter of familiarity. It took me months of working with LINQ before I stopped beginning my queries with the "select" clause. Now it is second nature, and the SQL order seems bizarre.

Which it is! The scoping rules are all messed up in SQL. Something you might want to point out to your coworker is that LINQ was carefully designed so that (1) introduction of variables and scopes happens left-to-right (*), and (2) the order that the query appears on the page is the order in which it is executed. That is, when you say

from c in customers where c.City == "London" select c.Name

the c appears in scope at the left, and stays in scope through the right. And the order in which things happen are: first "customers" is evaluated. Then the "where" is evaluated to filter the sequence. Then the filtered sequence is projected by the "select".

SQL doesn't have this property. If you say

SELECT Name FROM Customers WHERE City = 'London'

then "Name" is brought into scope by something to its right, not to its left, and the query is executed in a completely messed up order; the middle clause is evaluated first, then the last clause, and then the first clause. That now seems crazy and unintuitive to me, having worked solely with LINQ for so long now.


(*) Scoping rules are a bit weird in LINQ with join clauses. But other than that, scopes nest nicely.

share|improve this answer
2  
Nitpick: In German, "Der Hund frisst das Fleisch" is actually the same order as in English, "The dog eats the Meat" :) Aside from that, I found LINQ Query syntax very readable once i realized it was not SQL. –  Michael Stum Mar 8 '11 at 0:22
10  
@gbjbaanb: I am not justifying the LINQ syntax on the entirely subjective basis of it being more understandable. Rather, I'm justifying it on the entirely objective basis that it is far easier to design tools that assist the user in the construction of LINQ queries because the LINQ syntax was designed with tooling in mind, and that it is easier to mentally understand the order in which events happen in a query because they come in the same order lexically. –  Eric Lippert Jun 7 '11 at 6:11
1  
I admit SQL doesnt follow it either (where its WHERE clause comes last). A more intuitive way from a human perspective would be SELECT name WHERE id = 90 FROM table. You're right SQL is neither there nor here and messed up, but not too bad. Just saying. In the end I will have to say Within scoping rules Linq wins and is perfect, but when it comes to readability SQL wins though it is not perfect there –  nawfal Nov 21 '12 at 20:16
3  
I want a cup of coffee from starbucks where the store is open until midnight. Does that sounds familiar to you? It's in the exact same order as a SQL query. Yes, LINQ may be more readable than the unnecessary code you have to generate to execute a standard SQL query, but LINQ is not more readable than the SQL query itself. So yes; it might be advantageous for the LINQ developers to scope from left to right, but as a user, why do I care? I only care about usability. –  KyleM Mar 8 '13 at 17:01
4  
@KyleM: Of course; usability was a very important aspect of the LINQ design. In particular, being amenable to productivity tools was key. Because scoping flows from left to write in a LINQ query, by the time you type c. the IDE already knows the type of c and can give you IntelliSense. In LINQ you say "from c in customers where c." and boom, you get IntelliSense helping you by listing the members of Customer. In SQL when you type "SELECT name FROM customers" you can't get any IDE help to tell you that "name" is a good choice because you typed name before customers. –  Eric Lippert Mar 8 '13 at 17:41
show 3 more comments

Like anything else in the programming world, you gotta get used to the syntax, and then it is (potentially) easier to read.

Like anything else in the programming world, there is the potential for spaghetti code or other abuses.

Like anything else in the programming world, you can either do it this way or another way.

Like anything else in the programming world, your mileage may vary.

share|improve this answer
add comment

Lambda Expressions leads to less readable code if queries are too long. However it's much better than too many nested loops.

It's better with a mixture of the two.

Write it in Lambda if it's faster (you need it to be fast) or easier to read.

share|improve this answer
    
Yes, but what would make it linq/lamda not easier to read? –  BlackICE Dec 9 '10 at 16:11
    
sorry, meant not easier to read than the alternative. –  BlackICE Dec 9 '10 at 16:22
add comment

I saw a comment/remark where it stated something - in relation to LINQ/lambda - along the lines of: "Write code readable to humans, rather than readable to your computer".

I think that this statement has a lot of merit, however, consider the developer (such as myself) who has been through the full gamut of development languages from Assembly, through procedural, through OO, through managed, through leveraging high throughput task parallel solutions.

I have prided myself on making my code as readable and as reusable as possible and adopting many of the GOF design pattern principles in order to deliver production quality systems and services across a wide number of disparate business sectors.

The first time I encountered the lambda expression I thought: "What the hell is that!?!" It was immediately counter-intuitive to my familiar (and therefore comfortable) explicit declarative syntax. The younger < 5yrs in the job guys however lapped it up like it was manna from heaven!

That is because for years thinking like a computer (in the syntactic sense) translated very easily into direct coding syntax (irrespective of the language). When you have had that computational mindset for circa 20+yrs (30+ in my case) you have to appreciate that the initial syntactic shock of the lambda expression can easily translate into fear and mistrust.

Maybe the co-worker in the OP had come from a similar background as myself (i.e. been around the block a few times) and it was counter-intuitive to them at that time? My question is: what did you do about it? Did you try to re-educate your peer into understanding the benefits of the inline syntax, or did you pillory/ostracise them for not "being with the program"? The former would probably have seen your co-worker come round to your line of thinking, the latter would probably make them mistrust the LINQ/lambda syntax even more and thus exacerbating the negative opinion.

For myself I had to re-educate my own way of thinking (as Eric infers above, it's not an insignificant mind-shift, and I had to program in Miranda in the '80s so I've had my share of functional programming experience) but once I had gone through that pain the benefits were obvious but - more importantly - where its usage was over used (i.e. used for the sake of using it), over complex and repetitive (considering the DRY principle in that instance).

As someone who not only still writes a lot of code but who also has to technically review a lot of code it was imperative that I understood these principles so that I could review items impartially, advise where usage of a lambda expression may be more efficient/readable, and also to get developers to consider the readability of highly complex inline lambda expressions (where a method call would - in those cases - make the code more readable, maintainable and extensible).

So when someone says that they "Don't get lambda?" or LINQ syntax, rather than brand them a luddite try to help them understand the underlying principles. They may after all have an "old school" background such as myself.

share|improve this answer
    
Interesting comment - I had this when I switched from strongly-typed, static languages to dynamic languages. Took me a while to adjust (fear and mistrust) and now I find it hard to go back, honestly. –  lunchmeat317 Feb 12 at 21:31
add comment

I think it depends in most cases (except when doing something very bizarre) on if you mean "readable" as someone getting the idea of what is going on or if they can easily find all the tiny little details.

I think link helps with the former, but often (especially when debugging) hurts the latter.

IMHO when I am looking at code I am unfamiliar with the former is hugely more important than the latter, so I find it much more readable.

share|improve this answer
    
Good point. The latter is usually covered by good unit test. –  Scott Whitlock Dec 9 '10 at 16:11
    
So you think the internals of linq evaluation makes it difficult to find all the details? Can you provide an example of when this may be? –  BlackICE Dec 9 '10 at 16:13
2  
@David: Linq expressions are not just lazy evaluated, they're expressions. The receiving code of a linq expression can actually modify the expression so it does something completely different, like a lisp macro working on s-expressions. For instance, when working with linq to SQL, it actually takes the expression where e.FirstName == "John" and translates that into a SQL query! It does that by looking at the uncompiled (but parsed) expression, seeing it's a comparison of a property called FirstName on a persisted entity, and it's comparing to a string, etc. There's a lot going on. –  Scott Whitlock Dec 9 '10 at 16:46
    
@david generally I dont find the details difficult to find until you start using linq against itself. A "simple" example of this that took me a long time to wrap my head around is this: bugsquash.blogspot.com/2008/07/y-combinator-and-linq.html but there are a lot more necessarily examples in some of the things people are doing with expressions in the dynamic, DynamicObject and IDynamicMetaObjectProvider areas. Where you draw the line as to what is linq is debatable, but as scott points out all of that stuff is available to/in linq because linq uses the same expression trees. –  Bill Dec 9 '10 at 17:40
    
@Bill all right, I'll give you that's tough, but y-combinator and high order functions are going to hurt most of our heads, it's like recursion, you get it or you don't. Is the recursive implementation of that easier to read (if you didn't know either one)? –  BlackICE Dec 9 '10 at 18:42
show 1 more comment

I find LINQ syntax intuitive and easy to read, especially since they put the FROM at the start where it belongs instead of in the middle like in SQL. But IMO lambdas are confusing and make the code harder to read.

share|improve this answer
    
Why do you think lambdas are confusing? Is it the type inference? –  ChaosPandion Dec 9 '10 at 17:30
1  
@ChaosPandion: First the type inference, and second, the symbol. Putting an = and a > together looks like a >= that someone screwed up and wrote backwards, and it tends to throw my brain for a loop. –  Mason Wheeler Dec 9 '10 at 17:45
    
@Mason - Do you like the syntax of Haskell (\x -> x * x) or F# (fun x -> x * x)? –  ChaosPandion Dec 9 '10 at 19:07
    
@ChaosPandion: No, not particularly. Lambdas may be quick to write, but I find them difficult to parse, especially when they become non-trivial in complexity. Your examples aren't that bad, but they tend to get a lot worse. –  Mason Wheeler Dec 9 '10 at 19:14
6  
@Mason: It sounds like you're objecting to lamdas being abused, rather than objecting to the idea of lamdas in the first place. –  Anon. Dec 9 '10 at 20:14
show 2 more comments

I agree with you that Linq syntax is not significantly different from T-SQL. I think your coworker might really be objecting to relational stuff getting mixed in which his nice and shiny OO code. On the other hand, functional programming takes a bit of getting used to, and a willingness to get used to it.

share|improve this answer
add comment

There is probably a reason why Linq sucks, just do try to make real world examples, instead of these textbook examples.

try to show this function in linqlamdathings and you will see, that all the beauty is gone, while the classic way remains readable. Not to mention deferred execution problems and setting breakpoints.

The truth is LinqLambdaThings are very useful in few cases and they are not thought to replace all the nifty object orientation that you guys never understood

    public IList<Customer> GetVipCustomers(IList<Customer> source, int maxCount)
    {
        var results = new SortedList<string,Customer>();

        foreach (Customer c in source)
        {
            if (maxCount == results.Count)
                break;

            if (c.IsVip && c.FirstName== "Aaron" || c.SecondName== "Aaron")
                results.Add(c.LastName, c);
        }

        return results.Values;
    }
share|improve this answer
3  
I think its source.Where(c => c.IsVip && c.FirstName == "Aaron" || c.SecondName == "Aaron").Take(maxCount).OrderBy(d => d.LastName); but its hard to read yours so I may have made a mistake ;) –  jk. Mar 14 '13 at 14:18
1  
In what way did you consider these to be textbook examples? That is actually production use code. It would help if you provided both your classic "readable" code and the linq/lamda version for comparison instead of expecting everyone to convert it. –  BlackICE Mar 14 '13 at 15:04
    
Did you register specifically to complain about LINQ? –  KChaloux Mar 28 '13 at 19:37
    
@KChaloux I think they were just trolling to be honest –  jk. Mar 28 '13 at 19:41
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.