Live data from Hacker News

LINQ Ruined My Favorite Interview Question

scottchamberlin.tumblr.com

211–218 of 218 posts

Re: LINQ Ruined My Favorite Interview Question

#211

Earlier quoted context omitted.

I get what you're saying, I understand it, and I agree with the pitfalls. But I really really really don't agree that one should avoid LINQ. Sure if you don't understand how it works, and how it impact the performance, you should use it less. But don't try and drag the language down because you find it difficult. LINQ is easily one of the best things that have happened to a mainstream language in a long time, and if…

But don't try and drag the language down because you find it difficult. Oh give me a break. My exact complaint about LINQ is the opposite -- that it makes expensive operations seem simple, which with all innovations in language means that mediocre programmers will start abusing it in all codebases. LINQ has a place. To say that one should be using it "all the time", however, is exactly as I said -- a canary in a coal…

So I'm guess you haven't done any programming with the reactive extensions yet?

Re: LINQ Ruined My Favorite Interview Question

#212
post #120

Earlier quoted context omitted.

You're right; it does need a (map key) line to be equivalent. I was thinking of http://www.leancrew.com/all-this/2011/12/more-shell-less-egg... , which wants the counts too. :) On a side note, I'd like to point out a key difference between this Clojure example and corresponding variants in C#, Python, &c: the Clojure variant has no variables . This isn't just a matter of concision: coming up with descriptive names is…

> Six uses of three formal variables, including the bewilderingly confusable countedWords and wordCounts, plus nine uses of the delightfully generic "x". I totally agree with you on this. >Even in the more compact C# example from this thread, consider: var top = (from w in text.Split(' ') group w by w into g orderby g.Count() descending select g.Key).Take(10); > This variant refers to the temporary variables w (for "…

Over the last ten years, I've read a lot of code. I maintain my own code, and I maintain others' code. Because I am not that smart, I try to simplify everything--to make large problems tractable for my little brain to reason about. In this process, I've come to the conclusion that good, maintainable code is:

1. As simple as humanly possible, so that the algorithm is easy to understand and change. Each component is isolated and can be understood and modified in isolation. Boundaries between component and environment are clearly thought-out.

2. As simply expressed as possible: broken up into distinct, well-organized functions, with descriptive, regular names for functions and variables, in context.

3. Well-documented; each function and each namespace come with contextual docs explaining their motivation, arguments, consequences, invariants, etc., with examples.

4. As short as possible, because humans have trouble holding large amounts of context in their head. Minimize the amount of scrolling or jumping between files necessary to understand the algorithm.

5. Well-tested, so that changes can be made freely. The test suite needs to be fast, so one can get feedback within seconds of making a change to the file; ideally a few milliseconds. A balance of typechecking, logical tests with mocks, integration tests, and full stress tests provides a continuum of safety.

I don't see these goals as particularly constrained to any language, but I will say that I feel best able to achieve them in a Lisp. Dunno whether that helps you project your problems at work onto me personally, though. ;-)

Re: LINQ Ruined My Favorite Interview Question

#213

Earlier quoted context omitted.

You've actually been pretty vague about the concepts you're criticizing, except for "LINQ". Now I can see you were alluding to just the deferred execution part (the "lack of memoization"). Basically, you're saying it's too easy to accidentally perform a computation twice by iterating through a sequence twice. Recurse on that problem and you get an exponential blowup. That is actually a problem mostly unique to LINQ a…

I haven't been vague whatsoever.

In your first post, everything is "linq is bad" in generic terms except for these two bits:

> "it falls apart in real-world persistent code with considered algorithms and storage"

> "it makes it so easy to do [grouping / sorting / etc] that developers start to resort to that as a catch-all magical solution that is costless because how much could a line or two of code cost"

With hindsight I know your issue is with LINQ's deferred non-memoized execution. It's really easy to enumerate a sequence twice, but every place you do that might add a factor of 2 to the runtime and so there's a danger of exponential blowup that must be avoided. But that's not what I see when I read the above.

The above reads as complaints about easy composability and worries about code monkeys failing to consider what the code they're writing will do. Those are standard "functional / high-level programming is bad" complaints. With hindsight I know that's not what you meant, but that's what it reads like.

Re: LINQ Ruined My Favorite Interview Question

#214

Earlier quoted context omitted.

You've actually been pretty vague about the concepts you're criticizing, except for "LINQ". Now I can see you were alluding to just the deferred execution part (the "lack of memoization"). Basically, you're saying it's too easy to accidentally perform a computation twice by iterating through a sequence twice. Recurse on that problem and you get an exponential blowup. That is actually a problem mostly unique to LINQ a…

I haven't been vague whatsoever.

[deleted]

Re: LINQ Ruined My Favorite Interview Question

#215

Earlier quoted context omitted.

You've actually been pretty vague about the concepts you're criticizing, except for "LINQ". Now I can see you were alluding to just the deferred execution part (the "lack of memoization"). Basically, you're saying it's too easy to accidentally perform a computation twice by iterating through a sequence twice. Recurse on that problem and you get an exponential blowup. That is actually a problem mostly unique to LINQ a…

I haven't been vague whatsoever.

[deleted]

Re: LINQ Ruined My Favorite Interview Question

#216
post #211

Earlier quoted context omitted.

But don't try and drag the language down because you find it difficult. Oh give me a break. My exact complaint about LINQ is the opposite -- that it makes expensive operations seem simple, which with all innovations in language means that mediocre programmers will start abusing it in all codebases. LINQ has a place. To say that one should be using it "all the time", however, is exactly as I said -- a canary in a coal…

So I'm guess you haven't done any programming with the reactive extensions yet?

And why would you guess that? Because I don't consider LINQ of Rx observers being a magic cure-all?

In fact, LINQ on Rx is a symptom of the classic LINQ issue -- don't have subscriber or source filtering, or coherent, useful events -- simply broadcast everything and through the magic, free filtering of LINQ all is solved in the consumer.

Re: LINQ Ruined My Favorite Interview Question

#217
post #120

Earlier quoted context omitted.

You're right; it does need a (map key) line to be equivalent. I was thinking of http://www.leancrew.com/all-this/2011/12/more-shell-less-egg... , which wants the counts too. :) On a side note, I'd like to point out a key difference between this Clojure example and corresponding variants in C#, Python, &c: the Clojure variant has no variables . This isn't just a matter of concision: coming up with descriptive names is…

In C# that could be: return new Swimmer("foo") { Style = "butterfly"} .swim(); It is unidiomatic to have Swimmer.swim return 'this', though. var result = new Swimmer("foo") { Style = "butterfly"}; result.swim(); return result;

The thing being that C# has a feature for a whole bunch of idioms, but none of them are extensible and writing new ones requires a new version of the language. The Clojure reducers, doto, ->>, go macro could all have been implemented in 1.0. (And two of them were.)

I speak as someone who codes in C# for work and Clojure as a hobby. There's lots of things that just aren't quite possible in C#, and _everything_ is possible in Clojure.

Pointfree is beautiful to read and grok. It's a little trickier to debug, since pretty much every debugger on earth needs points to inspect values.

Re: LINQ Ruined My Favorite Interview Question

#218
post #207

Earlier quoted context omitted.

I'd never heard of Big O until this thread, but from what I can tell it'll only be when a solution is in the O(logn) that "running time will get less significant as n gets larger". This is simply the way you describe logarithmic growth, so maybe that's where you got confused. Also, wouldn't it be fair to say that a logarithm (nlogn) is a lower order term than mn? In which case your definition stands. At any rate, I w…

Oh, you're right, m is not a constant but also varies somewhat independently of n, so you can't exclude it from the big O notation. And whether mn or nlogn is the lower order of the two terms depends highly on the value of m, which is the number of unique words in the text. A really long text that's just the same word over and over will have a big n but a small m.

Worst-case big-O runtime is therefore O(n^2), and best case is O(n log(n)) :)
Post reply on HN