Hacker News new | past | comments | ask | show | jobs | submit login
21 Nested Callbacks (michellebu.com)
362 points by ericz on March 27, 2013 | hide | past | favorite | 113 comments

I love this. The code may not have been beautiful, but it worked, and the author figured it out themselves!

I'm simultaneously reminded of two different quotes:

Let's argue about whether Haskell or Clojure is better while somebody else ships products using PHP and duct tape. --@agentdero [0]

And the other:

<dm> I discovered that you'd never get an answer to a problem from Linux Gurus by asking. You have to troll in order for someone to help you with a Linux problem.

-- Bash.org [1]

You should always try to do SOMETHING over being frozen in indecision. Additionally, we really should do a better job of explaining things to people, so they don't have to stoop to trolling for answers :)

[0] https://twitter.com/agentdero/status/174965036928868352

[1] http://bash.org/?152037

"I discovered that you'd never get an answer to a problem from Linux Gurus by asking. You have to troll in order for someone to help you with a Linux problem."

This is one of my Jedi-level secrets of technical management.

I am quick to say I have a huge ego, because anyone who knew me would fight to say it first. The fact that I know what I know and have a good feel for where I'm weak lends me confidence in those situations where I'm mostly out of my depth.

I've managed ultra-introverted developers for about makesmesoundold years. Numerous are the times I've asked a question and gotten no answer. "How would we go about accomplishing x?" "How long would it take us to do y?" "What letter comes after z?"


Throw a proposal just plausible enough that people think you're serious, but so "insane" that it almost defies logic ("what if we put, say, hmm...log base two of 2097152 is 21...jQuery callbacks in an HTML file full of id'd divs..."), then it's as if a tiny rock starts rolling down a hill. First one person offers a criticism, and then we get more people engaged, throwing out the alternatives that they would have suggested in the first place.

Eventually, they recognize the game, and then it's a fun brainstorming activity. Or you fire three as a message to the others.

"Or you fire three as a message to the others."

This got my upvote. ;-)

Blog post writer here. I was going to mention this in the post, but I ended up deciding against it:

I'm from Middle America. In Middle America, when you ask a farmer what he feeds his pigs, he tells you what he feeds his pigs, what he doesn't feed his pigs, why he feeds his pigs what he feeds his pigs, how he feeds his pigs, and what sunscreen he applies to their skin.

So it was very weird to me that a lot of programmers didn't like to share their knowledge of programming (except, it seems, when they are trying to impress other programmers).

It seems to me that farmers spend a long time agonizing over what to feed their pigs, but don't often get to talk with people who are interested in hearing what they feed their pigs. To have someone to braindump to is a delight.

For programmers, everyone is trying constantly to braindump to everyone else; that's half of what the blog posts on HN consist of. And everyone wants their braindumps analyzed, and, more importantly, debugged. "I'm feeding my pigs horse meat--did I make the right decision?"

When you're exposed to it so often, it's hard not to get tired of telling people about the benefits of grain over horse meat.

See, I've always really liked explaining how things worked in the abstract to people, and most of the time, they also enjoy it. There is a logic that flows through programming that is beautiful and I feel innately understandable, even for the most abstract of programs. However, it often requires a lot of explanation and of laying out an intellectual base on which to build your mental construct. That's hard, but I've always found it so worth it:

The person listening learns something new, and is able to see something beautiful in the way that someone else sees it. Additionally, the person who's doing the explaining gains the experience of trying to relate their idea to another person, an exercise that often expands the explainers understanding of the idea.

I really wish more people explained what they love and find interesting!

I think that kind of explanation--explaining what you want to explain, with whatever tangents you like, just to get the other person to feel passion about the topic--is great, and can leave you feeling more invigorated than when you started.

But it's a very different kind of explanation than "here are all the building blocks you need to put together in order to understand how wrong the way you're currently doing things is." The second kind is pretty much what all "innocent programming questions" require in response.

I love these kind of interactions; both listening and explaining equally! I find I can elicit these kinds of explanations from others by being actively interested, reading how they react and what they emphasize, and asking the right questions to really get at their passion.

I exhort everyone to strike up these kinds of conversions especially with strangers as often as possible - I guarantee you will learn something interesting :) Ever since I got the hang of it, it has really enriched my life.

I have a great mentor who will often lead me up the garden path and get me nodding with him, then scuttle his own argument and let me know why it's bad. It's part entertainment for him (and me), part making me think before blindly agreeing, and partly history lesson/why they went this way.

Done properly, it's fun, though you do need some form of ongoing trust - it's not something you should do to someone piping up for the first time on IRC.

I'm a midwest boy who grew up on a farm, including working it from a very young age. Don't underestimate the farmer. Farmers will talk shop as much or more than programmers.

Feeding pigs is the tip of the iceberg. If you want to see some sparks fly, just sit down at the local cafe and talk about the comparative yield of soybeans and corn, and why anyone growing X percentage this year with the weather pattern is just plain nuts.

It's not quite the same as the family-farm days (most are now corporate owned), but those were the first debug sessions I listened in on as my grandfather held court among his colleagues.

I kind of want to punch the guy who said "no programmer would do this" in the nose. I'm glad you didn't let that person tell you who you were, or what you could be.

You wanted to do a thing. You made the computer do that thing. Programmer.

It's not about proving you're the smartest person before you even touch a keyboard. It's about being persistent, doing experiments, and always learning.

And I expect that your friend has forgotten the sort of things he did when he started.

Personally I interpreted it without any ill intent, more in the sense that no programmer would do it this way because programmers are lazy, they'd recognize "there's got to be a better way".

Confirms my suspicion that code is the most direct extension of biological evolution we've seen thus far.

> I kind of want to punch the guy who said "no programmer would do this" in the nose.

From my reading, it appeared as a complement as in "no beginner programmer would actually go through the pains of finishing it, and finishing it on your own is a feat."

Cheeseburgers, you don't even need to ask the farmer about slopping his pigs. Just ask for directions.

"Slow down when you get to the old Willoughby place, you'll know it by the brick shed they built in back, because the statey likes to sit behind the hill and catch speeders, and after five minutes, you'll want to go left..."

I grew up on the extreme western frontier of Flyoveria, in Eastern Washington State. We had a culture of the same sort of accreted experience that results in journeymen in their various careers. There's a reason a lot of phrases such as "college boy," "doesn't know sh8t from Shinola," etc. tend to be more common, and it's not just because they're "folksy." On the other hand, they really want to save people from themselves if they're willing to learn, and they'll tell you all you need to start farming pigs. You'd better be ready to help him with his computers, though, even if he's running his farm on a Kaypro II.

In programming, there's not as much of a long-term investment in the apprentice-journeyman-master guild-style system, although you can find pockets here and there. I have lamented it and pondered the reasons for its erosion over the past 20 years, but I can't say with real authority why we don't have it any longer, other than an expected lack of tenure at any organization.

It's not like big law or finance, where your first firm is there to grind you out of the business before your second firm decides if you're up or out.

Hi, I used to write code like your 21 nested callbacks, so I'm baffled by your friend's assertion that no programmer would be so patient. I've always thought that the patience to grind endlessly at a problem (or bug) without an obvious solution was one of the more laudable shared virtues of our tribe. Patience is, in fact, a vital part of my learning process.

In fact, I think that's probably a part of the reason why some programmers don't have patience for beginners with a lot of questions. It's because beginners actually have Google and StackOverflow these days, so it might seem like laziness to someone who had to learn using books and man pages. It's not that they don't like to share their knowledge, it's that they think the answer is already there if you'd bothered to look. I'm not saying that they're right to have that attitude, by the way. I'm just trying to present things from their perspective.

Yes, but that "patience to grind endlessly" is typically applied towards a different goal.

Sure, you can spend an afternoon or so to write and debug those 20 nested callbacks, but surely, it is more fun and thus better to spend a couple of _days_ thinking of the problem, googling for solutions, getting distracted by some nice algorithm, attempting to apply that in a totally distinct, perfectly working part of your codebase, renaming a couple of functions, etc., and finally replace that nested thing with some carefully placed '.each' or '.map' (after gauging which solution looks best, aesthetically)

Yes, there may be commercial pressure to ship a product, but in the hearts of many programmers, the journey is the reward.

"I divide my officers into four groups. There are clever, diligent, stupid, and lazy officers. Usually two characteristics are combined. Some are clever and diligent -- their place is the General Staff. The next lot are stupid and lazy -- they make up 90 percent of every army and are suited to routine duties. Anyone who is both clever and lazy is qualified for the highest leadership duties, because he possesses the intellectual clarity and the composure necessary for difficult decisions. One must beware of anyone who is stupid and diligent -- he must not be entrusted with any responsibility because he will always cause only mischief."

Granted, Kurt von Hammerstein-Equord was a nazi fuck and was talking about leadership, but I have found the best programmers are extremely lazy, however they have a constant drive to figure things out, take them apart, and put them back together again. They also generally have a need in the same vein of "write programs so they don't have to do the work of copy pasting 100 times in the first place" even if they spend 4 hours figuring out to do that.

I'm just trying to figure out at which point this conversation invoked Godwin's law... Seems ambiguous in this case.

Did you read my post?

"Granted, Kurt von Hammerstein-Equord was a nazi fuck"

Nope, you didn't.

Did you read his link?

"He is famous for being an ardent opponent of Hitler and the Nazi regime."

Nope, you didn't.

I think that the lack of patience refers more to dislike of redundancy - to an experienced programmer (including present-day OP), the repetition in that code seems absurd; there simply must be a way to refactor it into something simpler. We go out of our way to make tools that automate repetitive processes, we have principles like DRY, etc. Once a problem is solved it should stay solved.

"Most of you are familiar with the virtues of a programmer. There are three, of course: laziness, impatience, and hubris." -- Larry Wall

I think that really depends on whom you ask. For many (maybe even most) people I know, you would get too much information. With maybe a nice detour into theory. (Most of the best things in CS come with deep but surprisingly simple and elegant mathematics behind it.)

Of course, the information might also be a bit biased: everyone has their own preferences and opinions, and usually present them fairly strongly. Some people hedge about other options half-heartedly, but I doubt anyone would give you an even spiel on more than a couple of different options. Which is entirely natural: chances are, nobody has much experience with more than a couple of different options.

This might also vary a bit by community. I haven't spent much time recently talking to web developers. But the general programming languages/functional programming community is certainly fairly talkative.

I heard a different version:

Young farmer: I got some pigs, but I don't know what to feed them. What do you feed your pigs?

Old farmer: I had some pigs once, I fed them one of my cows that had died of consumption.

Young farmer: Really?

Old farmer: Yup.

<2 weeks later>

Young farmer: One of my cows died, so I fed it to my pigs. They all died. Your pigs really thrived on meat of a diseased cow?

Old farmer: Nope, my pigs died.

Huh- that seems weird to me too - my experience is that programmers generally love to share their knowledge and talk about their field. My tendency when newbies ask me about programming is to share as much info as possible, possibly too much - but then, I've been known to bust out my laptop at fancy dinner parties and start demoing how to write HTML.

Ah... like you said, I'd always felt that programmers try to help each other, so I was surprised when I read that the OP thought that wasn't true.

I think I see what might've been going on now, though; I don't think it was because the question "What's CSS?" (or similar) is too dumb, and I especially don't think that it's because no one wanted to help you (or thought you're incompetent).

Rather, it's because when you're starting to program, you don't _know_ that you can Google the solutions to so many problems so easily, so you ask the people around you. It's perfectly sensible. So, one of the things that programmers try to teach other beginning programmers early is that Google makes a lot of information easy to access, and so they try to help you by telling you that you can Google before asking.

It's not that they don't want to answer, or that they feel you're hopeless -- they're just trying to teach you how to fish, instead of giving you a fish. :) I'm sure if you ask the exact same question _after_ you have failed to find the answer after a 2-minute search on Google, you will not be turned down for the answer -- programmers generally love to help each other figure out how to do stuff. And one of these things they like teaching is that you can find answers to a lot of questions online!

That's amazing! We should've been friends.

Hi Michelle!

That's not too hard to explain. Some programmers see themselves as part of a clique. Their code and ways are what keeps them superior, experts in the field that they work in. The sunscreen that coats their javascript perhaps took them a hard couple hours of debugging to discover, and many programmers are the type of people who feel and rationalize "If it took me this long, this newb should go through the same process".

Of course, there are many exceptions- all the online communities, forums, etc. But there's always some part that does work as I described. Hell, even I get annoyed sometimes and tell someone who's starting out "go google why you don't want a GOTO statement in code"...

Programmers see themselves as part of a clique. Their code and ways are what keeps them superior, experts in the field that they work in.

Any programmer who thinks like that is a poser.

OT, but speaking of cliques and programmers, it seems that I've hit that point again where after you get around 1000 HN karma somebody from the upper echelons clips you (slow ban, etc) as not to threaten them.

I'm not sure why this always happens just after the 1000 mark.

Artificially reducing some ill-considered "competition"?

... and they will address you by your first name on a public forum, showing how friendly they can be to the normals.

Because I'm her friend IRL?

If someone asks me a programming question then I always answer it in the simplest, shortest method possible unless I already know they are at a good skill level.

I think the farmer can reasonably expect a layman to understand most of the things related to feeding pigs.

I, on the other hand, have no expectation that a layman would understand pointers, lambdas or any of the other lovely complicated things that even answering simple questions COULD entail if we went into details or expanded around the question.

[EDIT: Apologies it this comes off as arrogant or elitist or something, not intended.]

Yeah I can definitely see how jargon prevents that level of conversation. There's definitely a false analogy in my original statement--there's plenty of jargon in farming and raising pigs as well, but I personally do know a decent amount on the topic so I'm not really a layman in the conversation that I had imagined in my head.

Hey OP, kudos on finding a solution. However, I want to see the original, can you provide a link?

It's in the post :).


Sorry for missing it!! Cool looking effects, kudos again ;)

This is probably one of my favourite comments ever.

The Linux Guru line reminds me of a technique I used to get quick Mac OS help many, many years ago. Emailing a friend for that sort of help often left me with a long wait, so I'd email two rabid Mac people in the same email, let them see that both had been included, and then watch as they fought over themselves to quickly show how the Mac solution was so fast and easy.

One of the main reasons PHP is still kicking is because it's still easier to get things done with PHP.

I find that true. For most people, having messed with accessible things like bash scripts or .bat files in Windows, the approach that is taken in PHP, where the act of accessing a file runs the code in it's contents, is quite intuitive. I know that for me PHP was by far the easiest web-app language to come to understand when I started programming.

And the other is its ubiquity on cheap hosting.

Agree, I thought it was really neat.

The fact that she went through with it and got it to work, despite how it ended up looking, is commendable.

And I really like the result. Anyway, this article was neat and put a smile on my face.

> (I gathered from these exchanges that programmers have a perpetual competition to see who can claim the most things as 'simple.')

Amusingly, I've noticed the same thing: I do claim that a surprising amount of things are simple. And you know why? Because they are. A whole bunch of things (most recently F-algebras and F-coalgebras) really are simple: you start with a very simple concept (say sets and functions) and build up to them, taking very simple steps along the way. Maybe you have to bring in a couple of other concepts that are similarly simple.

EDIT: I should have made this clearer: I say something is simple before trying to explain it rather than instead of. I mainly do it to avoid scaring people without reason, and everyone gets far too scared of words like "F-coalgebra" or even "monoid".

Every single step along the way? Virtually trivial. But put them together and you get something genuinely difficult to follow.

It turns out that enough trivial steps all building upon each other becomes difficult to follow for anyone. Yet, once you've finally understood it, you can't see why it was difficult any more: after all, all the components are so simple, and it all makes sense! (Now.)

I realized this in a pretty direct way: I was trying to explain the aforementioned algebras to some of the smartest people I know--people with much more mathematical experience and aptitude than me--and they all found it a bit hard to follow. Not because they couldn't follow any particular step, but because putting it all together in your head is difficult.

So really, the ultimate conclusion is: just because something is simple does not mean it is easy. Having some trouble with simple concepts like this is not an issue at all; everybody does. But that doesn't mean they aren't simple!

Another, more surprising, conclusion is just how shallow the stack of concepts has to be to cause people trouble. It's not like there are hundreds of parts in these definitions: there are maybe 10. (Say: set, function, algebra, identity, category, morphism, functor, dual.) And yet this is more than enough to confuse.

That's something that I think laypeople never realize about computer science - it's all really simple things, but combined together at such a scale and pace that in a few decades we've done the equivalent of building a cat from scratch out of DNA. Big complex things really can be built out of extremely simple parts, and we're doing it all the time, but for a lot of people our technology is indistinguishable from magic.

Markets too, in the end they are all just information, limit and market orders.

Well put. I have the same experience with compilers and program transformation. Many small steps, all of them simple , lead to a lot of heavy lifting if you put them all together. In some sense all those steps are "orthogonal", each taking the path into a completely new direction, ending up far away from the initial point, conceptually.

> "No, no programmer would do something this." He was not sarcastic. I wanted to switch back into Molecular and Cellular Biology right then. But then he added, "No one would end up with code like this because they simply would not have had the patience."

My brother and I learned to program in BASIC on an Apple IIe when we were kids. At the time, we were also into making little movies with our family's VHS camcorder. You could draw graphics in BASIC, so we thought it would be radical to write a program that would draw a cool logo animation for our movies.

We got a big sheet of graph paper and hand-drew the intended pixel art for our logo. Then started writing code to draw it one line at a time. We put a delay between each line so that it would do an animated wipe. We knew how to pause by doing a busy loop:

    10 FOR I = 1 to 100
    20 NEXT I
What we didn't know was how to define reusable procedures (GOSUB). So between each of the hundred lines of pixel art, I typed in that loop. And I mean that literally: this was a line editor. No copy and paste. I wrote it out each time.

Now I just lament having the much free time and focus to be able to do that...

Supposing you could travel back in time and give your earlier self a book (or at least, a few sheets of paper) that described 'good programming' (e.g. using GOSUB, in this context) - would you do it?

Would you have been better off 'doing things right' from day one, versus experimenting and muddling through?

> (I gathered from these exchanges that programmers have a perpetual competition to see who can claim the most things as 'simple.')

Nobody hits my brother but me.

Programmers are persistently frustrated in our tools-- when you can see how things work, you start to see just how broken it all is. Things that should be easy are hard, things that should be hard are nearly impossible. And for every thing gotten right, there's something a little subtler that's completely and opaquely wrong, wasting days of your life. We hate our tools, and we love to complain about them.

But if you complain about our tools... Sorry, who are you? This is basic stuff.

"A poor craftsman blames their tools."

We're in a funny profession where we're both the people making and using the tools.

In other professions, blaming your tools is essentially a "There's nothing I can do about it -- the tools just suck."

In programming, we can go "These tools suck, but I can fix them". Of course, then you never accomplish what you initially set out to...

Who is "we?" I use pretty much vanilla vi/vim and SublimeText (or whatever comes next) so I'm not ever hamstrung a possible lack of tools.

I see this attitude as being like a lot of hot rod restoration people I've known: they like working on cars, but seemingly not necessarily driving. They don't ever want to be done, so they keep finding broken stuff, and the end result is that their "tool" is always broken. The Lego castle can always use another brick, you know? When do they ever drive, and if they do, are they happy when they do it or are they complaining inside the entire time? "Engine feels a little rough" is "my computer seems slow" is "that could really be automated." To me it's all just stuff that is other-than-coding. Pretty much just give me a fuzzy-filefinder with `screen` and I'm good, I gave up tinkering quite a while back.

From OP: "Programmers are persistently frustrated in our tools-- when you can see how things work, you start to see just how broken it all is. Things that should be easy are hard, things that should be hard are nearly impossible. And for every thing gotten right, there's something a little subtler that's completely and opaquely wrong, wasting days of your life. We hate our tools, and we love to complain about them."

"We" is programmers as a group, in

> We're in a funny profession where we're both the people making and using the tools.

I don't mean that every single programmer is making and using the tools, just that the skillset for making and using the tools is pretty similar.

Note that I said "we can go <bla>". I'm not really advocating stopping what you're doing to tinker with your tools. It's just that it's often a tantalising possibility which people in other professions are less tempted by.

As you say, though, if you want to get anything done, you have to resist the temptation.

I love that the author was persistent enough to actually get to a solution -- any solution, no matter how ridiculous -- using nothing more than Google. I can't count how many times I've tried to help someone get started on the basics of the web programming stack only to realize that the inferential distance for this person is so high that I would have to spend hours explaining things in order to help them solve the problem.

Sorry world. It's getting better. But slowly.

I recall being a novice and learning Java, and trying to solve http://projecteuler.net/problem=5 - I had nested if statements like "if(x % 20 == 0) { if (x % 19 == 0) {..." and I was thrilled that it worked. I have since learned far better ways to accomplish things like that; but I probably wouldn't have if I had just given up in frustration and never become a professional developer. Cool job by the author in posting the original code. I'm too embarrassed to post my nested-if business :)

Great article.

For a while, I was even hesitant to simply show some of my projects to other developers I looked up to..I figured the code was so bad, and the project so trivial, that why bother?

Reading sites like HN, you read about these tremendously talented people.... doing exits, building absurdly cool projects that you think you'll never be able to build... and it's easy to benchmark yourself against that sort of ideal and think that your stuff isn't cool enough. When I finally was confident enough to share some projects with a few people I respected, I was blown away by how much I learned just listening to their feedback.

Even if you think you're code sucks, you'll improve rapidly by learning WHY it sucks, and using that in new projects.

My real regret after reading this post: my early code is lost. Git didn't exist. Maybe SVN did but I wouldn't have had a clue.

To my genuine amazement, the company I worked for immediately after leaving college is still using a program I wrote for them seven years after I wrote it. When I left, they said that every company operation was going to be covered by SAP- weird how that didn't work out...

But still, it was written in VB.NET (!) and was a horrible, horrible mess. I would love to take a look at that code now, but I'm afraid that if I contact them they'll hold me responsible for updating it.

Be glad. My forays into programming have been gitified. It's like these teenagers growing up with social media and cameras everywhere. They'll always have those years to haunt them :P

I just wasted about 30 minutes writing a short solution, when I could have written the 22 callbacks in about 5 minutes. I did learn quite a bit about jquery, and the fn.delay isn't great. The funny thing about programming is that it does seem simple once you have a solution.

    function animate_opacity_to(opacity) {
        var elems = $('[id^=row]').get();
        (function x(){
            var el;
            if(el = elems.pop()) 

Actually, jQuery animate includes a built-in animation queueing system for this exact purpose, so callbacks really aren't necessary at all! For example:

  function animate_opacity_to(opacity) {
      $('[id^=row]').forEach(function(el) {
          $(el).animate({opacity: opacity}, {duration: 100, queue: true});
(haven't tested this but I think it should work.) In general, I've found that using a queue or queue-like structure can often help alleviate the dreaded "callback waterfall". Instead of saying "do this, then when you're done, do this, then when you're done, do this", you're saying "here are a list of the things I want done, do them in order and don't start the next thing in the list before the previous one is done". If you have some things in the queue that can be run simultaneously, you can combine them with a Deferred (see http://api.jquery.com/jQuery.Deferred/ )

In any case, great article - I definitely remember many similar scenarios that came up while I was learning to code. Sometimes you just gotta go with the crappy implementation you know will work rather than the efficient implementation that is beyond your current understanding :)

I tried something like your code, but it doesn't work. The queue parameter defaults to true, and it only applies to the set of elements in the jQuery object.

What will work is adding `delay` e.g.

But that causes other problems because frantically clicking will cause the animations to get queued. Setting `queue` to false, breaks .delay().

After some reading, it seems animate attaches a deferred on the element, so this works:

		return l.pipe(function(){
			return $(r).animate({opacity:opacity}, 100);
	}, $.Deferred().resolve());
Obviously, you can put any selector in there and you'll get them animate in order. Hence, allowing you to play with many combinations, once you spend the time to write this once. I agree with the OP about getting something done is always better than nothing. Yet, the responses that s/he got from programmer friends is not an issue of technical pragmatism, but one of collaboration culture. Unfortunately colleges are like that. Things are different in more professional settings.

Your comment made me look up reduce(). Just when you think you know javascript, good code like yours throws me back to researching. If I didn't see this, I would have continued to use underscorejs to do a reduce().

Hmm, with .reduce() you have:

		return l.pipe(function(){
			return $(r).animate({opacity:opacity}, 100);
	}, $.Deferred().resolve());
but without .reduce() you have:

    var pipeline = $.Deferred().resolve();
    $('[id^=row]').each(function(index, row) {
        pipeline = pipeline.pipe(function() {
            return $(row).animate({opacity:opacity}, 100);
(untested) which is, to my eyes at least, more readable. Just because you can do anything with .reduce() that you can do with a for loop doesn't mean you should.

The assignment in the loop breaks the readability for me:

In the reduce case, the deferred is in the scope of the function as a named argument; which is the main advantage of using deferred in this case. In the .each loop, deferred is a variable in the outer scope. Even though it looks like it will work (need to try), I wouldn't consider it the safer and more readable solution.

I guess I think of mutating a variable repeatedly as a pretty normal thing for a loop to do, nearly the only reason for having a loop, and you can see what the data flow is from the source code. In the reduce case, you kind of have to guess what the arguments to reduce() and the anonymous function are. I mean, if you'd gotten the l and r arguments backwards in your function, could you see that from looking at the code? What if you'd gotten the arguments to reduce() in the wrong order? (And you don't get to see what the initial value is until you finish reading the function that updates it.)

I think reduce() is awesome for associative operations and in general reasonable in point-free style. But I don't think its use in this case improves readability.

I agree, it is normal to mutate a variable within the loop. I find code more comfortable to maintain when the side effects are reduced. Add the pipeline variable to the .reduce:

  var pipeline = $.Deferred().resolve();
  		return l.pipe(function(){
  			return $(r).animate({opacity:opacity}, 100);
  	}, pipeline);
But, more than avoiding mutations, thinking of the loop as a .reduce made it easier for me to write the code. The reduce has a semantic goal of computing one value out of the array, besides explicitly handling intermediate results, e.g. in this case, you can think about the .reduce as computation of a single deferred that will fire when everything completes, whereas you can get to the same effect with the .each loop by using the pipeline variable.

  var alldone = $('[id^=row]').toArray().reduce(function(l,r){
  		return l.pipe(function(){
  			return $(r).animate({opacity:opacity}, 100);
  	}, $.Deferred().resolve());
The conceptual boundary between .each and .reduce is blurred due to the two-phase nature of this code, i.e. the outer function runs as soon as the execution hits the statement and traverses all the elements, and the inner function runs as the deferred chain fires and consumes the deferreds. .reduce allowed me to think both the inner and outer functions to run as a reduction; even though the outer is really a loop.

Interesting thing about code reviews: 10% of the code generates 90% of the discussion.

The time difference between the dead-simple (and ugly) solution that we almost all shy away from ("it burns us!") and the more elegant solution is especially interesting.

Reminds me of the first pseudo-3D thing I wrote back in high school. I'd borrowed one of my brother's 3D graphics books and came across the simple algorithm for depth drawing (x = x0/z, y = y0/z), and immediately set to work writing a wireframe space shooter in Pascal.

I was so eager to get the graphical part out there that I didn't think about the problems of modeling, or having multiple objects on the screen at once. The whole thing was a single-file, thousand-line, hard-coded mess. And I still think it was awesome.

I've been getting pretty sick of the whole "look how dumb I am, but I'm iterating!!!11" meme, but I really like this post. As a young person working in a company of people with far more experience, I've asked my share of stupid-simple questions and made my share of dumb mistakes. Luckily, I've got enough experience with programmers to get the most out of these interactions (also helpful to have decent human beings for co-workers!)

The important thing is to remember that there aren't (m)any super geniuses for which this stuff spews out first try. It's just that some people had the benefit of working through their ridiculously terrible code at the age of 8, writing BASIC, or whatever. And while they may have to learn jQuery the same as you did, they have a massive class of "intuitive" knowledge, which is really just experience, to help them through most of it.

Programming may or may not be hard, but it's not a good idea to think of it as hard. You need the laziness that makes you think, as soon as you get to callback 3, "there must be a better way than this". Occasionally you're disappointed, but generally if you know programming is easy then it will be.

We all have written code only to come back to it a few weeks later and think "oh god, what in the world was I thinking". If only code refactored itself over the time; small projects aren't an issue, but there's a point in every devs life when you have this monstrous one-eyed, ten thousand lined class that works fine in production but no one knows how or why it works and the idea of making a single change to it gives you pure panic and terror. And you know you have to rewrite it, but you have a hard time justifying spending two weeks on getting nothing tangible done, so to speak. The class goes on unfactored for a while (until it inevitably breaks) but at least you come to this almost zen realization that beautiful code = simple, short, and self descriptive code.


I like this quote:

"I gathered from these exchanges that programmers have a perpetual competition to see who can claim the most things as 'simple.'"

So many people like this quote that I wish I had structured the sentence less awkwardly.

I found it perfectly simple.

No reason you couldn't change it now. :-)

I used Michelle's website last year when I was looking for examples of how to write good CSS and HTML - I definitely couldn't have told you then that she had started web programming less than a year ago!

It just goes to show that if you really have a passion for something and you really work hard at it, you can become awesome at it (or at least good enough to know you can be awesome without that much work) in no time. I find that this usually holds for most things in life, but it lends itself to web design especially.

I know Michelle, and it's impressive that she started coding just two summers ago. Testament to the fact that it doesn't take long to become a good programmer

I just clicked to the fact she's the same person behind PeerJS.

Impressive is a slight understatement.

Depends on your definition of "good programmer".

Haha, I'm a programmer who will write 21 nested callbacks no more :). That's enough for me to claim for now.

Unless I'm missing some wit, that seems uncalled-for.

And judging by her github profile, she's a good programmer by any reasonable definition.

Sorry, I was not attacking anyone in particular. It's just that there are so many facets to programming, and being good at it really depends on the context.

That said, anyone that learns from their mistakes will become great.

21 nested callbacks sounds like my current attempt at twisted programming,except Michelles code is a lot clearer and easier to read! Even more experienced people write complete rubbish in an new language or worse port their old language patterns over. No shame in being a beginner.

"Be a better beginner," has served me well over the years.

This reminds me of some of my earlier excursions into coding. For example, early on I needed to be able to randomly select from a set of 100 numbers. Not knowing about arrays, but knowing about classes and the random module I created a class that had 100 fields, and a method that contained a giant if-else tree to select one. Of course, I did not want to write out all of that, so I ended up creating an excel spreadsheet, and used that to mass produce a bunch of the repeated lines.

To the writer of the post: my thanks. You brought a smile to my face. The awe at the complexity of programming is something I felt a long time ago, when I was 9 or 10. It is still vivid, and your post brought back memories and a smile.

Just goes to show that talent is as much inate as it is countless hours bashing against the wall. I had a lot of patience when I was 9.

This reminds me of a novelty I created early on in my programming career. I wanted to recreate the color picker from Photoshop (I think version 4) on a webpage. This was several years before jQuery and "Googling" it would have produced meager results. After considerable effort and writing equally "elegant" code as the OP, I had a 256 x 256 grid of divs displaying my color picker. Little to no CSS in that bad boy, but a ton of javascript hex conversions. The page loaded soooooo slow and brought my computer to it's knees, but I was very proud of it. I did actually use recursion, but not to the degree I could have if I had more knowledge. The achievement was not in writing perfect and optimal code, but in having an idea and seeing it through to completion.

Well...it seems like Eric Z. and the UC Berkeley Hackers@Berkeley club really can easily vote their way up on HackerNews. It's happened more than once and its not a coincidence :\ Still, amazing article and learned a lot in 5 minutes :)

Nowadays whenever I see a callback waterfall forming, my first thought is https://npmjs.org/package/node-async.

Yep there's plenty of solutions to callback hell.

My particular favourite is the Lamina library in clojure which takes the event-driven approach https://github.com/ztellman/lamina/wiki/Introduction

You should take a look at C#'s 'async' and 'await' keywords, which keep code asynchronous code looking sequential:


OP is in a pretty unique form of callback hell. a list, a function, and a for loop would suffice.

I find those 21 nested callbacks strangely elegant.

This reminds me of the days when I was learning, even before I got into college. Fortunately, we as an industry have more resources than any other field for beginners, but as lelandbatey said, "...we really should do a better job of explaining things to people,..." - +100

Everyone I know who codes or designs is anxious to help others learn to do the same. However, it's just common decency and respect to Google it, try to do it, and then have specific questions about what you couldn't get past.

Just a rebuttal to one point that irked me.

See, getting value out of Google is something that's learned over time. At the very beginning it was hard to get very far at all with just Googling and when I asked others they pointed me back to Google--some of them unhelpfully, but others showed me how to use better search terms for the subject at hand.

That helped a lot, and I don't resent them for that type of help at all. I'm sorry if it came across that way in the writing.

> See, getting value out of Google is something that's learned over time.

This is very true. Especially early on, while learning basic concepts, I found it very difficult to Google things because I did not know the terms or concepts involved. When I was attempting to self-teach my first programming language (Python), I could not understand the difference between parameters and arguments - but I didn't know that that was how to characterize my problem either. I just thought "why doesn't 'x' mean what I said it means over there?"

Thank you for posting this. I had never thought about how understanding the terminology required to Google was something that needed to be built up over time. Need to keep this in mind.

I love this code, reminds me of my seven-level cascade in server-code javascript.

And it's always funny to go back to our beginnings and see the difference in code and level after only some years :)

I hate snob programmers and designers.

It isn't very uncommon to have code that would cause most to projectile-vomit in products that are massively successful, reliable and, yes, very profitable.

For design, there's always Craigslist.

"Programming is hard." No it's not. Resources are everywhere today ,tons of books , Stackoverflow , tutorials ,etc ... you cant accuse programmers of not wanting to share their knowledge ,that's not true , they all do.

You have entire and complex projects on github available for free , so no Programming is not hard , it takes time to become a good programmer yes but like everything else in life. You want to try something hard ? try to be a doctor instead.

Programming IS hard. You can ask the PhD. Computer Science students at any decent college and they will tell you that they are humbled because the field of programming is so vast and wonderful and full of mystery. I think we can admit that we have discovered .000000000000000001% of the things that can be discovered at this point in the field of programming.

I think you overestimate our knowledge of programming. Still, it seems like the pace of discovery has slowed down considerably since the 1960s, for whatever reason.

Programming is hard, but that's where the fun is. Writing 21 nested callbacks isn't that hard especially with some copy and paste, finding a solution that does not look that ugly is hard, but otherwise programming will be really boring. I mean writing code that merely works is boring most of the time. If finding an elegant solution is not more fun than finding a working solution for you (those who enjoyed math knows what I mean), then programming maybe not your thing.

Thats pretty pointlessly dismissive. Its great that there are people who like finding elegant solutions to problems but in the same hand its also great that there are people who care more about solving users problems than generating pretty code. (I would count myself in the latter group)

I am not really trying to dismiss people how care more about solving users problems. In that case, product is your thing, and I love love love to work with a product person who is passionate about solving user problems. But I doubt I would enjoy maintaining the code written by product person who doesn't care that much about "pretty code".

Very rarely would it be your job to enjoy maintaining that code.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact