I am wary of designs that make code significantly longer, as both these examples do. The improvement in local readability is often superficial and the cost in overall readability (not to mention bugs, which increase with code size) is often nontrivial.
In the examples, each line of code with a named function appears more readable, but this is only because its meaning has become less dense—and as there is also now more code to read, the two factors arguably cancel each other out. Meanwhile the new code has more non-locality: the eye of the reader must jump between the various function invocations and declarations. That's a lot of jumping, and it will get much worse as complexity grows.
Introducing a name has costs as well as benefits. For example, it adds indirection: the name now stands between the reader and the thing that is named. To overcome this, a name should say something about the problem the code is solving. If all it says is something about the code itself, that's not good—it adds weight and obscures the problem (because you're now taking more code to solve it). It feels like you're simplifying code by factoring it in this way, but you may only be spreading it out more, making pieces which are logically bound together further apart from each other.
A sign that this is happening is when you can't think of a good name for the code you are factoring, or when the name refers only to the code itself. "wtfFriendAction" is a comical example, but I think "gotFriends" is more instructive: it tells you nothing more than "I am the callback for getFriends", and thus adds no information to the original code, only verbosity.
I don't think naming your functions has to make the code "significantly longer". Perhaps 2 lines per callback.
And yes it can be hard to name functions, and I think the OP has not created very good example, but a good name that accurately describes what the function does means I don't have to read it if I don't want to.
A better example would have been some node.js code that has 5 levels of nesting, each with a some significant code within.
Right, but now your functions are very tightly coupled to each other. The indentation might be nicer, but functionally it's just misleading.
The cool thing about promises is that your methods are pretty portable. For example:
function getUserFriends(userName, next) {
db.users.findOne({name:userName}, foundOne);
function foundOne(err, user) {
if (err != null) return next(err);
db.friends.find({userId:user.id}, foundFriends);
}
function foundFriends(err, friends) {
if (err != null) return next(err);
return next(null, friends);
}
}
Can be rewritten (using q[0]) as:
var Q = require('q');
function getUserFriends(userName, next) {
var deferred = Q.defer();
db.users.findOne({name:userName}, deferred.makeNodeResolver());
return deferred.promise;
}
function foundOne(user) {
var deferred = Q.defer();
db.friends.find({userId:user.id}, deferred.makeNodeResolver());
return deferred.promise;
}
function foundFriends(friends) { ... }
getUserFriends.then(foundOne).then(foundFriends);
You'll see here that getUserFriends, foundOne, and foundFriends (which I left out) are now all portable and can be used elsewhere in the code for other purposes (because they are no longer tightly coupled).
The real problem with callbacks is error handling. Using anonymous functions doesn't address this problem. The .then notation has the same problem.
The await solution (or any equivalent) has the benefit to present the call as a synchronous call which is trivial to read and understand. It also has the benefit to support all existing and proven error handling methods. try catch, etc.
This is the best solution to asynchronous calls that I have seen so far.
I'm currently using c++ asio, and it's a nightmare.
How can you make this argument and not even mention the word 'closure'? That's like arguing there's no need for object orientation, and demonstrating it by showing how you can model any class as just a set of global functions, by only showing classes which have no instance state.
Replacing anonymous functions with named functions works fine unless the anonymous functions are closures. If they are, you're going to have to add parameters to them to pass state in, and you're in real trouble if you want to have them modify closed state, because in JavaScript you've got no pass-by-reference. But closures that modify closed variables are hard to reason about in the usual nested callback syntax model.
What the async 'syntactic sugar' approaches do is replace nested closure scopes with simple control-structure scoping that's easy to reason about - even if the 'callbacks' are modifying state which then gets made available to subsequent callbacks.
It looks like you opened the article, hit "ctrl+f closure", saw 0, and went on a rant. In the examples where the turned an anonymous function into a named function, the named functions still close over symbols from their calling context, so... it's hard to see what you're on about.
I think callbacks are still pretty broken even after applying the "two rules". Yes, one avoids nesting, but you still break your procedure/function/method into chunks which make no sense by themselves.
I don't see how that can lead to good code. Better than a million nested callbacks? Sure. Readable? Nope. How do you even name all those callbacks?
"Callbacks are Pretty Okay" translation: I'm a programmer in my twenties, work mostly in Javascript, have no much experience with the historic literature and core ideas of Compute Science, don't know any better, and I like node, so there.
This recent 'callbacks as goto' discussion is so utterly mundane that I've all but failed to convince my wrists to so much as twitch sufficiently to click on any of the links, just the title is enough to drive me to drink.
Callbacks are in no way "this generation's goto", they do not in any way inhibit the ability to analyse or prove correct a program, and all alternatives to callbacks amount to incredibly fancy syntax sugar for hiding what is really happening behind the scenes anyway.
A callback is a function call, or put another way, a specification of an exact set of arguments grouped in a formal specification that is sent to a deterministic little machine (the function) to execute immediately. On completion the machine will provably produce the result it promised to return in its owner's manual (i.e. the declared return code).
None of this is "goto" in any way. In goto land, without knowing the exact set of inputs a program receives and whole-system simulation, it is utterly impossible to make assumptions about even the most minimal pieces of state in the program at any given moment.
Contrast to a function call. A function call is a fixed guarantee about the state of the system at the point a machine begins executing. Furthermore a function call has a vastly restricted set of valid behaviours: at some point it must terminate, and prior to termination, update the system state (stack) to include its return value. And upon termination, result in the calling machine to resume operation.
All this syntax sugar shit is whack. Great, you typed 24 characters instead of 3 lines to declare a lambda. Hyper productive, go you. How does this progress toward the point where I can say "computer, make me a coffee!"?
If you're genuinely interested in what this generation's Goto might look like, take 30 minutes to watch http://vimeo.com/71278954 .. our UIs are utterly trapped in pre-1970s thinking, our communication networks are so utterly idiotic that we STILL have to write custom code to link disparate chunks of data and logic together, we're STILL writing goddamned function calls in a freaking text editor (something that was solved LONG ago). All the things like this.
I can't ask my computer to make me a cup of coffee, and it responds. I can't describe in restricted English a simple query problem and have the millions of idle machines around the world coordinate meaningfully to answer my question (and our best chances of this.. freebase.com.. got bought up by Google and left to rot as some vestigial appendage of their antispam dept no doubt).
Computing is in a sad state today, but not because of fucking callbacks. It's in a sad state today because we're still thinking about problems on this level at all.
Node.js wasn't an innovation. It was shit that was solved 60 years ago. I wish more people would understand this. Nothing improves if we all start typing 'await' instead of defining callbacks.
Innovation in our industry has been glacial since at least the early 90s.
Edit: and as a final note, I wholeheartedly welcome you to nitpick the hell out my rant, wax verbose on the definitions of provability, the concept of a stack, the use of English versus American language, why Vim is awesome, and in the process once more demonstrate the amoeba-like mentality 90% of our industry is trapped in.
Go and build a programming language your Mom can use. Preferably by talking to her computer. Please, just don't waste it on any more of this insanity.
They are very much analogous to GOTO -- or even COMEFROM.
They have a similar effect to the control flow, and a similar adverse effect on the understanding of the program.
And Dijkstra's core argument against GOTO applies 100%:
"""My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible."""
>all alternatives to callbacks amount to incredibly fancy syntax sugar for hiding what is really happening behind the scenes anyway.
If, for, while, foreach --heck even map, reduce et co, etc are also syntax sugar for GOTO. Your point? Or adding the weasel word "fancy" somehow makes this particular syntax sugar bad?
Not to mention that there's nothing "incredibly fancy" about await, async, promises et co.
And if I wanted to know "what's really happening behind the scenes" I wouldn't programmer in Javascript in the first place.
>they do not in any way inhibit the ability to analyse or prove correct a program, and all alternatives to callbacks amount to incredibly fancy syntax sugar for hiding what is really happening behind the scenes anyway.
1) EVERYTHING is 'syntax sugar'.
2) There's nothing intrinsically wrong with gotos, they just aren't very well suited for human brains. Computers can execute goto statements very efficiently.
Callback-hell smells very much like gotos to me. It's very easy to do the wrong thing and easy to create very hard to read, hard to understand, and hard to maintain code.
> I can't ask my computer to make me a cup of coffee, and it responds.
Question: what exactly would you like your computer--that beige box under your desk--to do, if you ask (or rather, command) it do do that? This sounds more like an embodied intelligence/robotics problem than a problem with constraint-solving goal-directed AI, per se.
Unless you want it to use Mechanical Turk to fire off a task to have a human make you a coffee. I could see that working, but it's probably not what you'd expect to happen.
If you truly believe that we're all missing the point, how do you propose it be fixed? How far down the stack do we need to start disassembling parts and rebuilding? And who, if anyone, is doing that now?
> [Callbacks] do not in any way inhibit the ability to analyse or prove correct a program
It's obvious to me that they do: humans are not that good at keeping track of these fragmented chains of flow control. They're just more balls in the air for the juggler.
In building systems, we are using many layers of abstractions all the time (or "syntax sugar" as you say).
Computing is in a sad state today, but not because of
fucking callbacks. It's in a sad state today because
we're still thinking about problems on this level at all.
The unfortunate part about thinking about problems is it that problems are relative - i.e. they are problems only relative to a context. Nobody even in the tech world has a clue how solving a simple problem just to satisfy some intellectual curiosity can affect life on the planet. What meaning does Wiles' proof of Fermat's last theorem have on the part of the world that's sleeping hungry every night?
The stuff we're talking about here has irked some pretty decent brains enough for them to go out and make ... another textual programming language.
Folks like Musk are an inspiration indeed for boldly thinking at the high level they do and seeing it through. However, that's exactly what's easy for press to write up on. Stuff like the moon speech is what's easy to communicate. It is also simple to attribute some great deed to one of these great "visions". But behind each such vision lies the incremental work of millions - each of it, I say, worth every penny - unsung heroes, all of them.
On a related point, not all the time where we've heard a call to greater action do we see the ability in those folks to imagine how that might come about.
> Furthermore a function call has a vastly restricted set of valid behaviours: at some point it must terminate, and prior to termination, update the system state (stack) to include its return value.
Hooray! We've solved the halting problem. Without formal analysis, it's not possible to show (in general) that a function will terminate.
More seriously, I've seen function behavior that's just as bad as other types of flow control (including gotos).
You're looking in the wrong places. Nobody thinks we're close to building a computer you mom can talk to, but we are getting closer to understanding what computer languages are and their properties. On that end research is blistering and exciting.
My Mom prefers to do her development in C, because she needs to make sure her search algorithms are very high performance. So it seems she already has a pretty good language for her use cases?
>incredibly fancy syntax sugar
In JavaScript yes but the way python handles async stuff is not 'fancy syntax sugar' it is actually very clever - I'm not saying Javascript should do things the way python does, they are fundamentally different and I actually quite like callbacks in javascript but I think you should be clear that your comments are made in relation to Javascript (assuming they were).
It occurs to me that if you're using a whole bunch of anonymous functions with nested lexical closures, then the shared state between them starts looking a lot like global variables.
And globals are evil, but relative to the other nightmares that Gotos could produce, they're pretty mild.
So true:
`Node.js wasn't an innovation. It was shit that was solved 60 years ago.`
We're just reinventing the same thing because some sh*ty stuff got momentum. Take websockets, how is now a webserver better then IRCD hacked with an implmentation of fcgi?
Thank you for providing some sanity to this callbacks inquisition. I am getting so tired of all the "callbacks are evil, js is evil" crusade. Sorry your pet language isn't supported by every browser ever.
> a freaking text editor (something that was solved LONG ago)
It wasn't solved, it was replaced by a different, and worse, set of problems. Other people having minds organized differently from yours isn't evidence of a usability problem.
The problem with programming isn't the syntax. The problem is teaching a Martian to smoke a cigarette: Giving instructions to something which shares no cultural background with you and has no common sense.
(Of course, the classic 'teach a Martian to smoke a cigarette' problem is rigged, because the students are never told what instructions the Martian can follow; therefore, anything they say will be misinterpreted in various creative ways depending on how funny the teacher is. On the other hand, playing the game fairly by giving the students a list of things the Martian knows how to do would reduce the thought experiment to a tedious engineering problem.)
> Go and build a programming language your Mom can use.
This sexism is worse than anything else in your barely-thought-through rant of a post. The blatant, unexamined sexism in this statement keeps fully half of the potential programmers from picking up a damn keyboard and trying.
I have a project in Go which is pretty heavily functional. Over time, I've begun to notice the general goodness of his 2 rules. If you didn't RTFA, they were
1. Avoid nontrivial anonymous functions.
2. Function declarations after the code that actually does things.
I wonder if his advice is good for all functional-style code in non-functional languages.
Nesting is not the problem, you see what you're doing (when you perform an async io request). And you still have the "if (e) return cb(e)" line... And on top of that, it does not look better.
I guess it comes down to preferences in readability.
Personally I agree that not putting too much logic in anonymous functions makes it more readable. I write my own code that way, but some might disagree.
I don't care about whether functions are above or below where they are used, as long as it is consistent - but event then it is a minor thing. And since it isn't enforced by the language (e.g. like in Clojure where you have to def the var/function above the reference) it is going to vary across code bases anyway.
I don't really think either solves callbacks, nor that callbacks is a problem to be solved. Most comes down to pros and cons seen through the filter of your personal preferences.
Sure you can use a language that compiles to javascript. Does the pros outweigh the cons for you? Great, use it/too bad move right along.
Not everything is right or wrong, good or bad - in fact most things aren't.
Thing is that it actually matters in JS because declaring a function this way triggers the hoisting mechanism, so named functions are in scope within the entire function in which it is declared, regardless of block nesting.
If one isn't careful, and because JS doesn't have the visual delineator of blocks, instead all these rules you have to memorize, this could easily could lead to bugs, especially in large code-bases.
I think it's good to rely on closures to keep from polluting your scopes and to not use uneccesary function names, which is going to lead to one giant imperative statement (the one with the sequence of commands for the computer to perform) rather than a lot of little functions that you can pass around. Secrets of the JS ninja goes really in depth about this.
An operation queue where dependencies can be set is also very relevant. For example, if you have to do 2 different json requests, followed by a render - but they are mutually exclusive, you can do a 2->1 dependency. If they do depend on each other's result, you can do a 1->1->1
I like this async syntax but I'm more fond of native JS generator trampoline. I think the JSOperation with dependencies could even use generators in its implementation.
All these solutions coming about after the C# async article are very enlightening to this problem of the synchronic vs diachronic vs asynchronic.
Thanks for this OP. I use these 2 rules in my every day JS because where I work, readability wins every time. The anon function / indentation code format is something I've never really tried to "pick up" when I migrated over to javascript. Its ugly and takes longer for someone outside of my head to figure out what is going on in my code. Verbose function names help the other 4 guys on my team know exactly which function is handling the different scenarios of an async call. Its much more important that the developers are able to work efficiently than it is to save a few characters per function or a few lines per callback.
With the state of JS compilers/minifiers and gzip, I really feel that that particular argument can't even be made in most JS situations.
I like Andrew's rules here, and reading over one of my recent node.js projects, I can see how they would have helped.
My code becomes cleaner and more maintainable when I am forced to name each chunk of 5-10 lines by putting them into separate functions/methods with defined inputs and outputs. This compartmentalization is naturally encouraged by java, C#, ruby, and python, but Javascript actually seems to discourage it.
The ready availability of anonymous callbacks in JS tends to allow for "function creep", where you blink twice and suddenly you have 50 tangled lines of code without obvious control flow or separation of concerns; sticking to named functions seems like it could definitely help.
I agree with the OP. Its all about how you structure and name your code to avoid deeply nested callbacks. With the use of Prototype constructs and decent directory structures you can keep code clean and concise and completely avoid callback hell.
Take a look at the following users repos to see exactly how clean javascript code can be.
This is essentially how I have been writing JavaScript and Node.js code for some time. I actually flatten the code even more, like in these examples[0].
For some people, callbacks take more cognition than other solutions, but for someone who has been using callbacks through and through, this is a natural progression and makes sense. It is more straightforward and you don't have to understand further abstractions like in a compile to JS language or with promises.
I never thought of using nested functions like that. It does make the code much more readable, and using 100% JS is a big win. Not as pretty as yield/await, but much more debuggable and compatible.
I think this is a step backward toward procedural programming (needing to name each function, ignoring the hoisting mechanism that happens when you declare a function that way) and then took another step back by putting it all in one huge imperative statement at the top). Probably going to lead to bugs if one isn't careful with the function scope. The best part about JS is that you can be use a functional, declarative style, which is awesome.
The main problem I see with callbacks is that people forget that deeply nested structures are too cumbersome to hold in one's brains. The OP rules to break down things in smaller, named function is a solution to a more general problem: don't nest things if you can avoid to.
Callbacks aren't the problem. People using them are the problem. Keep your logic as flat as possible and callback-hell will dissolves before your eyes.
[+] [-] gruseom|12 years ago|reply
In the examples, each line of code with a named function appears more readable, but this is only because its meaning has become less dense—and as there is also now more code to read, the two factors arguably cancel each other out. Meanwhile the new code has more non-locality: the eye of the reader must jump between the various function invocations and declarations. That's a lot of jumping, and it will get much worse as complexity grows.
Introducing a name has costs as well as benefits. For example, it adds indirection: the name now stands between the reader and the thing that is named. To overcome this, a name should say something about the problem the code is solving. If all it says is something about the code itself, that's not good—it adds weight and obscures the problem (because you're now taking more code to solve it). It feels like you're simplifying code by factoring it in this way, but you may only be spreading it out more, making pieces which are logically bound together further apart from each other.
A sign that this is happening is when you can't think of a good name for the code you are factoring, or when the name refers only to the code itself. "wtfFriendAction" is a comical example, but I think "gotFriends" is more instructive: it tells you nothing more than "I am the callback for getFriends", and thus adds no information to the original code, only verbosity.
[+] [-] jay_kyburz|12 years ago|reply
And yes it can be hard to name functions, and I think the OP has not created very good example, but a good name that accurately describes what the function does means I don't have to read it if I don't want to.
A better example would have been some node.js code that has 5 levels of nesting, each with a some significant code within.
You've just got to name them.
[+] [-] prezjordan|12 years ago|reply
The cool thing about promises is that your methods are pretty portable. For example:
Can be rewritten (using q[0]) as: You'll see here that getUserFriends, foundOne, and foundFriends (which I left out) are now all portable and can be used elsewhere in the code for other purposes (because they are no longer tightly coupled).[0]: https://github.com/kriskowal/q
[+] [-] StavrosK|12 years ago|reply
[+] [-] modiho|12 years ago|reply
[+] [-] chmike|12 years ago|reply
The await solution (or any equivalent) has the benefit to present the call as a synchronous call which is trivial to read and understand. It also has the benefit to support all existing and proven error handling methods. try catch, etc.
This is the best solution to asynchronous calls that I have seen so far.
I'm currently using c++ asio, and it's a nightmare.
[+] [-] lucian1900|12 years ago|reply
[+] [-] jameshart|12 years ago|reply
Replacing anonymous functions with named functions works fine unless the anonymous functions are closures. If they are, you're going to have to add parameters to them to pass state in, and you're in real trouble if you want to have them modify closed state, because in JavaScript you've got no pass-by-reference. But closures that modify closed variables are hard to reason about in the usual nested callback syntax model.
What the async 'syntactic sugar' approaches do is replace nested closure scopes with simple control-structure scoping that's easy to reason about - even if the 'callbacks' are modifying state which then gets made available to subsequent callbacks.
[+] [-] zemo|12 years ago|reply
[+] [-] sklivvz1971|12 years ago|reply
I don't see how that can lead to good code. Better than a million nested callbacks? Sure. Readable? Nope. How do you even name all those callbacks?
[+] [-] coldtea|12 years ago|reply
[+] [-] nly|12 years ago|reply
[+] [-] Tichy|12 years ago|reply
[+] [-] hosay123|12 years ago|reply
Callbacks are in no way "this generation's goto", they do not in any way inhibit the ability to analyse or prove correct a program, and all alternatives to callbacks amount to incredibly fancy syntax sugar for hiding what is really happening behind the scenes anyway.
A callback is a function call, or put another way, a specification of an exact set of arguments grouped in a formal specification that is sent to a deterministic little machine (the function) to execute immediately. On completion the machine will provably produce the result it promised to return in its owner's manual (i.e. the declared return code).
None of this is "goto" in any way. In goto land, without knowing the exact set of inputs a program receives and whole-system simulation, it is utterly impossible to make assumptions about even the most minimal pieces of state in the program at any given moment.
Contrast to a function call. A function call is a fixed guarantee about the state of the system at the point a machine begins executing. Furthermore a function call has a vastly restricted set of valid behaviours: at some point it must terminate, and prior to termination, update the system state (stack) to include its return value. And upon termination, result in the calling machine to resume operation.
All this syntax sugar shit is whack. Great, you typed 24 characters instead of 3 lines to declare a lambda. Hyper productive, go you. How does this progress toward the point where I can say "computer, make me a coffee!"?
If you're genuinely interested in what this generation's Goto might look like, take 30 minutes to watch http://vimeo.com/71278954 .. our UIs are utterly trapped in pre-1970s thinking, our communication networks are so utterly idiotic that we STILL have to write custom code to link disparate chunks of data and logic together, we're STILL writing goddamned function calls in a freaking text editor (something that was solved LONG ago). All the things like this.
I can't ask my computer to make me a cup of coffee, and it responds. I can't describe in restricted English a simple query problem and have the millions of idle machines around the world coordinate meaningfully to answer my question (and our best chances of this.. freebase.com.. got bought up by Google and left to rot as some vestigial appendage of their antispam dept no doubt).
Computing is in a sad state today, but not because of fucking callbacks. It's in a sad state today because we're still thinking about problems on this level at all.
Node.js wasn't an innovation. It was shit that was solved 60 years ago. I wish more people would understand this. Nothing improves if we all start typing 'await' instead of defining callbacks.
Innovation in our industry has been glacial since at least the early 90s.
Edit: and as a final note, I wholeheartedly welcome you to nitpick the hell out my rant, wax verbose on the definitions of provability, the concept of a stack, the use of English versus American language, why Vim is awesome, and in the process once more demonstrate the amoeba-like mentality 90% of our industry is trapped in.
Go and build a programming language your Mom can use. Preferably by talking to her computer. Please, just don't waste it on any more of this insanity.
[+] [-] coldtea|12 years ago|reply
They are very much analogous to GOTO -- or even COMEFROM.
They have a similar effect to the control flow, and a similar adverse effect on the understanding of the program.
And Dijkstra's core argument against GOTO applies 100%:
"""My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible."""
>all alternatives to callbacks amount to incredibly fancy syntax sugar for hiding what is really happening behind the scenes anyway.
If, for, while, foreach --heck even map, reduce et co, etc are also syntax sugar for GOTO. Your point? Or adding the weasel word "fancy" somehow makes this particular syntax sugar bad?
Not to mention that there's nothing "incredibly fancy" about await, async, promises et co.
And if I wanted to know "what's really happening behind the scenes" I wouldn't programmer in Javascript in the first place.
[+] [-] macspoofing|12 years ago|reply
1) EVERYTHING is 'syntax sugar'.
2) There's nothing intrinsically wrong with gotos, they just aren't very well suited for human brains. Computers can execute goto statements very efficiently.
Callback-hell smells very much like gotos to me. It's very easy to do the wrong thing and easy to create very hard to read, hard to understand, and hard to maintain code.
[+] [-] seanmcdirmid|12 years ago|reply
People who think this is doable with current technology usually don't have much clue in how to build a programming language.
[+] [-] derefr|12 years ago|reply
Question: what exactly would you like your computer--that beige box under your desk--to do, if you ask (or rather, command) it do do that? This sounds more like an embodied intelligence/robotics problem than a problem with constraint-solving goal-directed AI, per se.
Unless you want it to use Mechanical Turk to fire off a task to have a human make you a coffee. I could see that working, but it's probably not what you'd expect to happen.
[+] [-] STRML|12 years ago|reply
[+] [-] zurn|12 years ago|reply
It's obvious to me that they do: humans are not that good at keeping track of these fragmented chains of flow control. They're just more balls in the air for the juggler.
In building systems, we are using many layers of abstractions all the time (or "syntax sugar" as you say).
[+] [-] aufreak3|12 years ago|reply
The stuff we're talking about here has irked some pretty decent brains enough for them to go out and make ... another textual programming language.
Folks like Musk are an inspiration indeed for boldly thinking at the high level they do and seeing it through. However, that's exactly what's easy for press to write up on. Stuff like the moon speech is what's easy to communicate. It is also simple to attribute some great deed to one of these great "visions". But behind each such vision lies the incremental work of millions - each of it, I say, worth every penny - unsung heroes, all of them.
On a related point, not all the time where we've heard a call to greater action do we see the ability in those folks to imagine how that might come about.
edit: typos.
[+] [-] beambot|12 years ago|reply
Hooray! We've solved the halting problem. Without formal analysis, it's not possible to show (in general) that a function will terminate.
More seriously, I've seen function behavior that's just as bad as other types of flow control (including gotos).
[+] [-] tel|12 years ago|reply
But the industry has no need for that stuff.
[+] [-] kazagistar|12 years ago|reply
[+] [-] abritishguy|12 years ago|reply
[+] [-] jes5199|12 years ago|reply
It occurs to me that if you're using a whole bunch of anonymous functions with nested lexical closures, then the shared state between them starts looking a lot like global variables.
And globals are evil, but relative to the other nightmares that Gotos could produce, they're pretty mild.
[+] [-] 2mia|12 years ago|reply
We're just reinventing the same thing because some sh*ty stuff got momentum. Take websockets, how is now a webserver better then IRCD hacked with an implmentation of fcgi?
PS: vim is awesome :)
[+] [-] wslh|12 years ago|reply
Do you want callbacks? why instead of writing var a = 1 + 2; don't like to write:
var a; sum(1,2, function(result) { a = result; });
[+] [-] alexakarpov|12 years ago|reply
[+] [-] dccoolgai|12 years ago|reply
[+] [-] derleth|12 years ago|reply
It wasn't solved, it was replaced by a different, and worse, set of problems. Other people having minds organized differently from yours isn't evidence of a usability problem.
The problem with programming isn't the syntax. The problem is teaching a Martian to smoke a cigarette: Giving instructions to something which shares no cultural background with you and has no common sense.
(Of course, the classic 'teach a Martian to smoke a cigarette' problem is rigged, because the students are never told what instructions the Martian can follow; therefore, anything they say will be misinterpreted in various creative ways depending on how funny the teacher is. On the other hand, playing the game fairly by giving the students a list of things the Martian knows how to do would reduce the thought experiment to a tedious engineering problem.)
> Go and build a programming language your Mom can use.
This sexism is worse than anything else in your barely-thought-through rant of a post. The blatant, unexamined sexism in this statement keeps fully half of the potential programmers from picking up a damn keyboard and trying.
[+] [-] rob05c|12 years ago|reply
1. Avoid nontrivial anonymous functions.
2. Function declarations after the code that actually does things.
I wonder if his advice is good for all functional-style code in non-functional languages.
[+] [-] coldtea|12 years ago|reply
Are you fucking kidding me?
[+] [-] a__remie|12 years ago|reply
[+] [-] casperc|12 years ago|reply
Personally I agree that not putting too much logic in anonymous functions makes it more readable. I write my own code that way, but some might disagree.
I don't care about whether functions are above or below where they are used, as long as it is consistent - but event then it is a minor thing. And since it isn't enforced by the language (e.g. like in Clojure where you have to def the var/function above the reference) it is going to vary across code bases anyway.
I don't really think either solves callbacks, nor that callbacks is a problem to be solved. Most comes down to pros and cons seen through the filter of your personal preferences.
Sure you can use a language that compiles to javascript. Does the pros outweigh the cons for you? Great, use it/too bad move right along.
Not everything is right or wrong, good or bad - in fact most things aren't.
[+] [-] ulisesrmzroche|12 years ago|reply
If one isn't careful, and because JS doesn't have the visual delineator of blocks, instead all these rules you have to memorize, this could easily could lead to bugs, especially in large code-bases.
I think it's good to rely on closures to keep from polluting your scopes and to not use uneccesary function names, which is going to lead to one giant imperative statement (the one with the sequence of commands for the computer to perform) rather than a lot of little functions that you can pass around. Secrets of the JS ninja goes really in depth about this.
[+] [-] aa0|12 years ago|reply
I like this async syntax but I'm more fond of native JS generator trampoline. I think the JSOperation with dependencies could even use generators in its implementation.
All these solutions coming about after the C# async article are very enlightening to this problem of the synchronic vs diachronic vs asynchronic.
The JSOperations lib is in alpha but can be found here https://github.com/iandrewfuchs/JSOperations/blob/master/REA...
[+] [-] rickygw|12 years ago|reply
With the state of JS compilers/minifiers and gzip, I really feel that that particular argument can't even be made in most JS situations.
[+] [-] tkiley|12 years ago|reply
My code becomes cleaner and more maintainable when I am forced to name each chunk of 5-10 lines by putting them into separate functions/methods with defined inputs and outputs. This compartmentalization is naturally encouraged by java, C#, ruby, and python, but Javascript actually seems to discourage it.
The ready availability of anonymous callbacks in JS tends to allow for "function creep", where you blink twice and suddenly you have 50 tangled lines of code without obvious control flow or separation of concerns; sticking to named functions seems like it could definitely help.
[+] [-] nickjackson|12 years ago|reply
Take a look at the following users repos to see exactly how clean javascript code can be.
https://github.com/learnboost https://github.com/component https://github.com/visionmedia
[+] [-] chapel|12 years ago|reply
For some people, callbacks take more cognition than other solutions, but for someone who has been using callbacks through and through, this is a natural progression and makes sense. It is more straightforward and you don't have to understand further abstractions like in a compile to JS language or with promises.
[0]: https://gist.github.com/chapel/6255720
[+] [-] wingspan|12 years ago|reply
[+] [-] ulisesrmzroche|12 years ago|reply
[+] [-] AYBABTME|12 years ago|reply
Callbacks aren't the problem. People using them are the problem. Keep your logic as flat as possible and callback-hell will dissolves before your eyes.
Programming dogma is so annoying.
[+] [-] antihero|12 years ago|reply
How about this then? I haven't tested. Perhaps functions need to be in a different order, but we only have one level of nesting:
https://gist.github.com/radiosilence/2fd82aaf3b1721448ae1