Humans, in general, hate change. A large percent hate it so much that they actually fear it.
–
TonyDec 9 '10 at 16:05

8

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 WhitlockDec 9 '10 at 16:12

37

Does it bother anyone else that people tend to use the word "intuitive" when they really mean "familiar"?
–
Larry ColemanDec 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.
–
AaronaughtDec 9 '10 at 23:34

16

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 EversDec 10 '10 at 1:14

10 Answers
10

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.

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.

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.

+1 If you don't like LINQ its probably because "you ain't doing it right" :)
–
DarknightDec 13 '10 at 9:28

Linq is purely object-oriented +1 for this. This is also why our team style guide enforces using the fluent syntax over the query syntax. I find that makes the OO nature of link more obvious to somebody used to object notation in C-like languages.
–
SBIFeb 25 at 9:15

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.

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 StumMar 8 '11 at 0:22

15

@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 LippertJun 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
–
nawfalNov 21 '12 at 20:16

4

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.
–
KyleMMar 8 '13 at 17:01

7

@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 namebeforecustomers.
–
Eric LippertMar 8 '13 at 17:41

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.

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.
–
lunchmeat317Feb 12 '14 at 21:31

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.

Good point. The latter is usually covered by good unit test.
–
Scott WhitlockDec 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?
–
BlackICEDec 9 '10 at 16:13

3

@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 WhitlockDec 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.
–
BillDec 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)?
–
BlackICEDec 9 '10 at 18:42

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.

Why do you think lambdas are confusing? Is it the type inference?
–
ChaosPandionDec 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 WheelerDec 9 '10 at 17:45

@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 WheelerDec 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

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.

However; "more confusing than T-SQL?" - is discussed/asked in the initial question. This clearly implies some features that none of the existing answers address, instead accusing the (obviously SQL-acquainted) criticizer of being stuck in the past.

So although I appreciate LINQ for certain qualities, and don't greatly disagree with the existing answers here, I feel the counterpoint deserves representation:

Years after becoming familiar with LINQ, performing certain types of group operations, outer joins and non-equijoins, working with composite keys, and other operations in LINQ still make me cringe. (Especially when targeting a relational back-end with performance-sensitive questions.)

from c in categories
join p in products on c equals p.Category into ps
from p in ps.DefaultIfEmpty()

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.
–
BlackICEMar 14 '13 at 15:04

1

Did you register specifically to complain about LINQ?
–
KChalouxMar 28 '13 at 19:37

@KChaloux I think they were just trolling to be honest
–
jk.Mar 28 '13 at 19:41