TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Escape from Callback Hell: Callbacks are the modern goto

247 点作者 wheatBread超过 12 年前

45 条评论

tikhonj超过 12 年前
If you don't want to use another language and compile down to JavaScript--which is what Elm offers--there are some interesting options that are just JavaScript libraries.<p>The one I've personally played with is called Arrowlets[1], which introduces a control structure called an arrow that lets you abstract over callbacks and event handling (among other things). Using that style of programming can significantly simplify some fairly common tasks in JavaScript; the drag-and-drop demo on their site is a good motivating example. However, unless you are already familiar with functional programming and arrows, you should probably read some background before diving into the examples.<p>[1]: <a href="http://www.cs.umd.edu/projects/PL/arrowlets/" rel="nofollow">http://www.cs.umd.edu/projects/PL/arrowlets/</a><p>Another interesting option I've toyed with is RX.js[2]. This is a JavaScript version of C#'s Reactive Extentions (RX). If you are familiar with Linq, then this library's style should seem natural immediately. The core idea here is to abstract over events as streams that can be composed and manipulated conveniently.<p>[2]: <a href="http://rxjs.wikidot.com/" rel="nofollow">http://rxjs.wikidot.com/</a><p>If you don't mind using a different language, but want something that mostly looks like JavaScript, another option is FlapJax[3]. I haven't tried it myself, but I've certainly heard good things about it.<p>[3]: <a href="http://www.flapjax-lang.org/" rel="nofollow">http://www.flapjax-lang.org/</a><p>There are probably more options in the same vein that I forgot or don't know about. However, I think these three are a good starting point and could help clean up much of your event-driven JavaScript code in the short term.<p>Of course, if you are willing to use a language radically different from JavaScript, then Elm is a great option. Once you get used to functional languages with good type systems, there is really no going back ;). The syntax is also simpler and more minimalistic than JavaScript's, which leads to more readable code.
评论 #4735003 未加载
评论 #4734288 未加载
评论 #4734937 未加载
magicalist超过 12 年前
Callback hell is certainly a real thing, but that Javascript snippet is a poor example for a goto comparison, since it's pretty much as linear as you can get.<p>The problems with Javascript and callbacks are usually (in reverse importance): noisy verbosity (all those "function()"s), the deeper and deeper indentations, and then ensuring execution order on interdependent async steps while keeping it readable. In the blog post's example, you pretty much of a serial chain of dependent steps, and the only thing really wrong with it is that it's just ugly and approaching unreadable (syntax highlighting will help quite a bit, though).<p>I think most people heavily involved with Javascript recognize those problems, though. Promises/deferreds have entered mainstream js usage. They can be somewhat confusing for newcomers, but several libraries can help, as others have pointed out. Language support is evolving: "let" as an option for more control over scoping, the arrow syntax for simpler function expressions, yield for shallow continuations, etc. These will in turn feed back into making libraries smaller and easier to use (I'm really looking forward to when I can use <a href="http://taskjs.org/" rel="nofollow">http://taskjs.org/</a> for all my async needs. Combined with the arrow syntax, I feel like I can pretty much always avoid a callback mess and retain clarity of (high-level) flow at a glance).<p>This isn't a knock on elm (this article is the extent of my knowledge of it), and it isn't a dismissal of the problem, but it isn't clear to me from this article what is broken in JS that is fixed in elm. In other words, this could be another tutorial on promises in Javascript and make the same points about excessive callbacks being poor coding style and bad news for readability and maintainability.<p>Syntax that makes clear code the lowest energy state <i>is</i> a feature, but (if we limit our discussion to callbacks) in JS it's partly solved, partly being worked on, and it's not clear to me yet what the energy differential is in typical elm usage between this code and the nasty spaghetti code you can always write if you try.
ender7超过 12 年前
Personally, any solution to callback hell will also need to be a language that supports returning multiple values. The following convention is simply too useful to me:<p><pre><code> foo.doSomethingAsync(function(err, result) { if (err) { ... } ... }); </code></pre> You can obviously accomplish this with exceptions, but then you have a million try/catch blocks floating around all over the place and the code becomes even <i>harder</i> to read (and more verbose to boot).
评论 #4733950 未加载
评论 #4735206 未加载
评论 #4733981 未加载
webjprgm超过 12 年前
The "callback hell" example is a rather tame one, since the code is readable in a single location just with some nesting. So when I see the FRP solution which is the same amount of code I'm not certain that in a complex example this actually solves the problem. You can still have lift statements scattered around a program just like you can have callbacks to various functions scattered around.<p>The solution to GOTO was to remove it and replace it with a few control structure forms that enforced locality. I remember converting someone's GOTO-laced code once and basically everything could be re-written with some clever use of do-while with break statements and an occasional flag variable. do-while, while, for, etc. replace GOTO in 99% of cases and enforce the desired code locality for readability.<p>So what syntactical structure could enforce locality of time-connected variables?<p>E.g. some idea like this:<p><pre><code> data, err &#60;- $.ajax(requestUrl1) if( err ) { console.log(err) return } data2, err &#60;- $.ajax(makeRequestUrl2(data)) </code></pre> Where the &#60;- syntax could be like an = statement but say that the assignment and all following statements are placed in a callback.
评论 #4734263 未加载
评论 #4734467 未加载
评论 #4734361 未加载
debacle超过 12 年前
Callbacks are different than gotos in that they are aren't even remotely close to gotos.<p>With a callback, you can get into 'callback hell,' however the root cause of that is that you probably don't understand the nuances of properly architecting a solution that involves the power of first-class functions.<p>JavaScript is nice because the scoping of the callback is easily controllable through your invocation method, and if you've created a good object model then it's relatively easy to maintain an understandable state.<p>When you explicitly define callbacks like in the examples, you're tightly coupling the response handlers to their requests, which is a relatively poor implementation and will bite you in the ass later on.
评论 #4733528 未加载
评论 #4733811 未加载
评论 #4733511 未加载
评论 #4733681 未加载
Sephr超过 12 年前
One way to escape callback hell is to use a async.js (<a href="https://github.com/eligrey/async.js" rel="nofollow">https://github.com/eligrey/async.js</a>), which uses yield to abstract away callbacks. It's Firefox-only (JS 1.7+) though, but that can probably be resolved by using a JS parser and replacing every yield with JS 1.5 callbacks.<p>Full disclosure: I wrote async.js.
评论 #4734000 未加载
wyuenho超过 12 年前
The problem is not callback, the problem is that callbacks exists in Javascript.<p>Callbacks themselves, when used wisely, can often enhance code readability, hell LISP has had function references since forever, but I think the most complain about callbacks are actually complains about callbacks in noisy languages, mostly likely languages with noisy syntaxes like Javascript and Java. When read that way, the disgust towards callbacks do seem to have merits. As the author has pointed out, the 2 getPhoto() functions at the end express and do exactly the same things, but obviously the CoffeeScript version reads better.<p>Callbacks have been around a long time and I've never heard of people complain as much about them as people have for Javascript and I conjecture the reasons are as follows:<p>1) There's no named parameters (keyword arguments) in Javascript, so people pass around objects literals into functions to emulate them. 2) Making lambdas in JS is too easy, but the syntax is too noisy. 3) Oh so many aliasing of <i>this</i>; 4) Self-chainable JS libraries like jQuery makes the style of calling multiple functions too easy. But lines can only go to long before becoming unwieldy, so people tend to indent chained method calls multiple times. 5) No modules and global namespace pollution is frown upon, so people are hesitant to flatten deeply nested callback chains. 6) There are a dozen ways to make a JS class and/or object depending on frameworks, and they are not at all compatible.<p>All of these "features" coagulate in JS into giant blobs of snot like this:<p><pre><code> &#60;script&#62; $(document).ready(function() { var $main = $("#main"); $main. hide(). click(function(e) { $.ajax({ type: "POST", dataType: "json", contentType: "application/json", success: function(data, textStatus, jqXHR) { data['rows'].forEach(function(line) { $main.append($("&#60;p&#62;", { className: "row" }).append(line)); }); } }); }). show(); }); &#60;/script&#62; </code></pre> Words for the wise, when you see a shiny new jQuery plugin, stop, think for 3 minutes, and then put it inside a Backbone View or whatever your favorite framework is other than jQuery*. If you don't know anything other than jQuery, now is probably the best time to learn a few.
herge超过 12 年前
This reminds me of the pain of dealing with python's twisted library, albeit before inline callbacks were implemented.<p>Inline callbacks as implemented in python can make asynchronous code a lot easier to read: <a href="http://hackedbellini.org/development/writing-asynchronous-python-code-with-twisted-using-inlinecallbacks/" rel="nofollow">http://hackedbellini.org/development/writing-asynchronous-py...</a>
评论 #4735394 未加载
peterbe超过 12 年前
Isn't `yield` the solution to all the problems? It makes things responsive and avoids the callbacks entirely.<p>For example: <a href="http://www.tornadoweb.org/documentation/gen.html" rel="nofollow">http://www.tornadoweb.org/documentation/gen.html</a>
评论 #4734151 未加载
ccleve超过 12 年前
You've got to ask, why is async programming used at all? The reason is twofold: first, the C10K problem, where too many threads kill performance, and second, sometimes you want to have multiple tasks run in parallel.<p>There are fairly simple syntactical solutions to both problems.<p><pre><code> result = doSomeAsyncTask() result.yield() // drops the thread, picks it up on response // do stuff with result here </code></pre> This magic yield() doesn't exist (to my knowledge), but if it did, it would preserve linear code and also solve the C10K problem.<p>You could have similar code to solve the multiple task problem:<p><pre><code> result0 = doSomeAsyncTask0(); result1 = doSomeAsyncTask1(); while (result = getNextCompletedTask(result0, result1)) { // do something to result } </code></pre> A Future in Java does something like this, but it doesn't drop threads.
jblow超过 12 年前
Callback Hell is certainly a real thing. I decided 12 years ago that I would never use callbacks if I could avoid it (the only wai you can't avoid it is if an API forces you to use them); I have never looked back. Regular, simple, straightforward imperative flow control is a very powerful thing, and any time you give it up or make it more squishy and indirect, you had better be getting something <i>big</i> in return. Usually you aren't.<p>That said, what the article proposes as a solution is bananas. You don't need to do crazy functional acronym things; just don't use callbacks. Good C/C++ programmers in the field where I work (video games) do this all the time. It's not hard except that it requires a little bit of discipline toward simplicity (which is not something exhibited by this article!)
评论 #4734020 未加载
评论 #4735274 未加载
评论 #4733904 未加载
评论 #4735040 未加载
Jacob4u2超过 12 年前
The author offers an alternative that would require a change to the language. Callbacks and their use in "callback hell" are a little different than use of "goto"; "goto" appears to have an obvious alternative that was more logical to use already implemented in the language. For javascript, there is none of the nice syntactic sugar (reminds me a lot of C# recent async changes) that the author suggests and is not even being proposed for ECMA 6.<p>I agree it would be nice to have that stuff, and that callbacks can get a little hairy, but they are the best solution available at present. Shall we stop developing applications in the mean time while the language catches up, or even worse, browsers actually consistently implement the changes?
评论 #4733295 未加载
评论 #4733320 未加载
评论 #4733286 未加载
wglb超过 12 年前
This kind of confuses two important ideas, both discussed by Dijkstra.<p>The most popular was his article about gotos.<p>Another idea in his writings was that time-dependent programming was dangerous. He was talking about interrupt based programming specifically, and also addressed the common practice of some hardware to have asynchronous IO. You would start an IO operation, and go on and do other things, come back later and see the values there.<p>So these two things are not alike. They both cause confusion about what the program is doing, but they are not "like" each other.<p>To be a better programmer, it is good to read Dijkstra. It is really all about avoiding errors in programming.
darwinGod超过 12 年前
As someone who writes C code for a distributed system that uses event-driven callbacks ( Zscaler) (yes,the binding is at compile time), I was aghast when I saw goto's in the codebase. I mean,I believed programmers were indoctrinated with " using goto = goto hell". I have realized that if used smartly,goto's cause no problem-say in error handling. I can confidently say I have not seen a single bug because of improper usage of goto in the last 1.7 years. And we do a lot of interesting things in C,including talking to a Postgres database,having a messaging protocol layer,doing shared memory manipulation etc.
grimtrigger超过 12 年前
One thing I'd like to see from languages that compile to js: Some kind of evidence that output readability is a concern. You can make some beautiful abstractions, but if I can't debug it when things go wrong, then there's no way I would use it.<p>Not making any comments about Elm's output, but the author clearly doesn't consider it a priority in the post.
评论 #4737480 未加载
whatgoodisaroad超过 12 年前
This seems like a bad analogy. Dijkstra's paper was in favor of "structured programming",and the problem was that goto was too-unstructured. If anything, callbacks are excessively structured.<p>Also, why is nonlinear code a bad thing? If the program behavior should be nonlinear, then neither should the code.
评论 #4737491 未加载
chubbard超过 12 年前
Two observations. First, great how do we debug it? How can we see our signals between each step? How about beyond simple print/logging?<p>And two, I like his contrast between async vs synchronous flows, and recognizing synchronous style programming has many benefits that CPS doesn't. However, I think even this style still hasn't solved the bigger problem with asynchronous style programming. The ability to reuse it easily. In synchronous style programming I can reuse code and add to that block by calling the method, then after that method is done add my code.<p><pre><code> ... my code before ... var result = someMethod() ... my code after ... </code></pre> It's just that simple with synchronous style. With async style the author has to provide you a hook to hook onto the end or beginning of this flow (adding a callback param, returning a promise, etc). I think even with using signals you have the same issue. Without explicit hooks you can't hook more code onto it like you can with good old fashion synchronous programming. Not to mention error control flow is turned upside down too.<p>I'm intrigued by the ideas of signals over callbacks, but I don't know if they fix enough problems with callbacks yet.
评论 #4735967 未加载
评论 #4735564 未加载
评论 #4735565 未加载
jawns超过 12 年前
So, this Functional Reactive Programming stuff compiles to Javascript, right?<p>Is the resultant Javascript just a bunch of nested callbacks, as in the example the blog post uses to illustrate spaghetti code?
评论 #4733753 未加载
评论 #4733577 未加载
aurelianito超过 12 年前
Actually, callbacks are the Intercal's COME_FROM instruction (<a href="http://en.wikipedia.org/wiki/COME_FROM" rel="nofollow">http://en.wikipedia.org/wiki/COME_FROM</a>).<p>So, it is even worst!
absconditus超过 12 年前
Here are the slides from Evan's talk at Strange Loop:<p><a href="https://github.com/strangeloop/strangeloop2012/blob/master/slides/elc/Czaplicki-ElmMakingTheWebFunctional.pdf?raw=true" rel="nofollow">https://github.com/strangeloop/strangeloop2012/blob/master/s...</a>
jcampbell1超过 12 年前
@mpolun - It appears your account has been hell-banned. You need to create a new account so I can upvote your comments:<p>mpolun&#62; I agree that raw callbacks can get out of hand, but the typical solution in js is to use an event emitter (<a href="http://nodejs.org/api/events.html" rel="nofollow">http://nodejs.org/api/events.html</a>) or promises (like <a href="https://github.com/kriskowal/q" rel="nofollow">https://github.com/kriskowal/q</a>), the latter of which seems to be pretty close to what this article is talking about. Is there a fundamental difference, or are promises an example of functional reactive programming in a language without direct support for it?
cbsmith超过 12 年前
Voting up just for not using a "...Considered Harmful" headline, particularly since the author obviously is familiar with the idea.
grogs超过 12 年前
Another approach to async IO is CPS (continuations passing style), in which you write imperative style code. This imperative style code is then compiled such that the blocking IO operations are called with callbacks, which are the remainder of that block of code (the continuation) - allowing the calling thread to be re-used while blocking for IO. Relies on the continuation having access to the outer/parent/previous-part function via closures.<p>It'll be interesting to see if people start doing this. Requires people to understand continuations and closures (which more people have exposure to now via JavaScript), and library support.
评论 #4737444 未加载
halayli超过 12 年前
Agreed. It's one of the reasons why I wrote lthread. Implementing any non-trivial protocol over a socket for example will lead to callback hell. There are plenty of states to transition from/to and it's very easy to get it wrong no matter how good the code is structured.<p>Forget Javascript for a second, and take a look at a typical http proxy written in C using callbacks to see what a callback hell looks like. If 5 developers are working on such a project, it will require a lot of mental effort from each developer to keep the callback flow up-to-date in their head.
apeace超过 12 年前
Having programmed in many languages, but most recently Node.js for the last two years, I don't think "callback hell" is as big a problem as the OP makes it out to be.<p>Debugging huge, complicated, and even poorly written Node applications doesn't feel much different to me than debugging huge, complicated, or poorly written Java applications. Sometimes it's a pain, that's unavoidable. You can prevent it to an extent by writing clean, tested code.<p>I don't see a strong resemblance between goto and callbacks. The resemblance is just as strong between goto and any function, or class
vvpan超过 12 年前
I've been a JS (which is the land of callbacks) programmer for only a few months now, and I would disagree. Yes you can write deeply nested callback chains, but you don't have to most of the time. There are a couple of ways to avoid it.<p>* The async library mentioned by other posters helps a lot.<p>* Libraries like backbone make writing event-driven software easier.<p>But to sum it up: it's like anywhere else, bad programmers write "callback hell" code, and good programmers don't.
评论 #4734326 未加载
zimbatm超过 12 年前
I'm not convinced.<p>I'm not familiar with the last approach but it seems to me that with a couple of higher-order functions in JavaScript, the code will quickly become more manageable.<p><pre><code> function getPhoto(tag, handlerCallback) { asyncChain(requestTag, requestOneFrom)(tag, function(photoSizes) { handlerCallback(sizesToPhoto(photoSizes)); }); } getPhoto('tokyo', drawOnScreen);</code></pre>
sses超过 12 年前
I used a functional-reactive-language-that-compiles-to-javascript for a web app, in a project that lasted about 3 years. It solved callback hell, and solved some UI problems, but created some hard UI problems as well. I'm not sure how this would translate to a server, but some examples anyway.<p>It seemed impossible to completely escape imperative programming. Mouse click handlers for example were much more natural to write imperatively; changes made in the imperative code would propagate as signals in a reactive way.<p>Reasoning about what happened around the boundaries of imperative and reactive code was hard, especially as the application grew in complexity. If I have a UI element that depends on two other signals - think spreadsheet cell with a formula that depends on two other calculations - do I want to update it as soon as one signal changes? do I wait for both to change? Do I want different behaviors in different circumstances? It often led excessive layout changes as values passed through intermediate states, or code being executed multiple times unnecessarily.
评论 #4737499 未加载
bunderbunder超过 12 年前
The number of languages that compile to JavaScript is starting to become disconcerting.<p>How long until we get tired of adding epicycles and just specify a VM and bytecode standard that all the browsers can implement and all the client-side languages can compile to?
评论 #4733813 未加载
评论 #4733960 未加载
评论 #4733819 未加载
spatten超过 12 年前
Here's a google cache link: <a href="http://webcache.googleusercontent.com/search?q=cache%3Ahttp%3A%2F%2Felm-lang.org%2Flearn%2FEscape-from-Callback-Hell.elm" rel="nofollow">http://webcache.googleusercontent.com/search?q=cache%3Ahttp%...</a>
ams6110超过 12 年前
<i>It [synchronous call] basically dodges the issue of time-dependence by just freezing if it is waiting for a value. This blocks everything in the program. Mouse and keyboard input just piles up, waiting to be processed, presenting the user with an unresponsive app. This is not an acceptable user experience.</i><p>It depends on what else your user can realistically do before the call completes. In many cases the answer is "nothing." He needs the result of the call before he can proceed in his task. In simple web apps this happens a lot. In those cases I will often just make a synchronous call and avoid all the callback complexity.
评论 #4737489 未加载
vinayan3超过 12 年前
Callbacks do lead to hell. The back traces half the lead you now-where. I have been writing a scrapy crawler and sometimes when an exception happens it takes some grepping around to figure out where the value that is wrong actually was generated.<p>Has anyone touched the Google Chrome code base? It is quite difficult to start debugging problems because of the sheer volume of callbacks. Add to that the stack-traces are massive because of the use of templates and other C++ language features.<p>Async coding needs to be an abstraction within the language. I am curious how languages manage the shared memory. What about the risk of dead locks?
评论 #4735342 未加载
grannyg00se超过 12 年前
"It is pretty much the same as using goto to structure your programs."<p>I don't see how a self contained block of code can be equated to goto where the flow can bounce around all over the place.<p>The example callback "hell" code doesn't look any more complicated than the solution Elm code to me. Maybe the improvement is going over my head and I need to read it again. I just don't see it. Then again, I feel the same way about Coffeescript. These javascript helper languages just seem like an unnecessary added level of complication and cognitive load.
评论 #4733493 未加载
评论 #4734038 未加载
schd超过 12 年前
Does anyone recall the article a few months back that sort of dealt with callback hell? It was a concept from a different language (which one, I don't recall) that worked basically with returning 2 values and formatting your functions according to a general model.<p>Yes, that's a bit vague, but that's all I've got to go on. :)
jberryman超过 12 年前
Marginally related but IYI, I recently wrote a JS lib for writing loops with a delay, to avoid one instance of callback hell:<p><a href="http://brandon.si/code/dilly-dot-js-a-library-for-loops-with-delays-in-javascript/" rel="nofollow">http://brandon.si/code/dilly-dot-js-a-library-for-loops-with...</a>
ambrop7超过 12 年前
I think the author is missing the obvious and natural solution: let the programmer write code in a completely synchronous (blocking) style, but have the programming language execute it an an asynchronous and concurrent fashion. Something like that:<p><pre><code> # this appears very synchronous function getPhoto(tag) { var photoList = syncGet(requestTag(tag)); var photoSizes = syncGet(requestOneFrom(photoList)); return sizesToPhoto(photoSizes); } # Two getPhoto() "processes" are spawned. After this, # the language multiplexes between them via the (single) event loop, # in a single OS thread. job1 = spawn getPhoto('tokyo'); job2 = spawn getPhoto('tokyo'); # Wait for both of them to finish. This too happens in an asynchronous # fashion, i.e. calling job1.join() does not prevent the two jobs from # running. In effect at this point we have three "processes" running # (the main process doing the joins, the job1 process and the job2 process). photo1 = job1.join(); photo2 = job2.join(); drawOnScreen(photo1); drawOnScreen(photo2); </code></pre> Yes, I know this may be very hard to implement in Javascript/Node, because it fundamentally changes the way the JS engine needs to work.<p>NOTE: It seems this approach is not new; "green theads" seems to be the right term, and there seem to be a lot of Python-based implementations. Go's goroutines also appear similar (but you can have them run truly in parallel).<p><i>BUT</i> note a crucial difference from the "green threads" approach - in my suggested design, there would be no real scheduling. If you perform sequence of operations and they are all guaranteed not to block, this sequence is <i>automatically atomic</i>, and cannot be interrupted by another "process".<p>I should also mention this programming language I'm developing, called NCD [1], which employs the same idea. See the in-browser demo [2], click on the Spawn example.<p>Note that NCD implements a unique extension of imperative programming. Statements in general persist even after they have "returned", and they get the chance to do stuff when they are about to be "deinitialized" (see what happens when you click "Request termination" in the Spawn example). Plus, any statement can trigger "backtracking" to its point within the process, causing automatic deinitialization of any statements that follow (try Count example).<p>Also, IMO promises [3] are just a hack around the fact that the language is not inherently asynchronous. Seriously, who would prefer:<p><pre><code> doFoo() .then(function (foo) { return doBar(foo); }) .then(function (bar) { return doBaz(bar); }) .then(function(baz) { console.log(baz); }); </code></pre> Over this?<p><pre><code> function myWork () { foo = doFoo(); bar = doBar(foo); baz = doBaz(bar); console.log(baz); } spawn myWork(); </code></pre> [1] <a href="http://code.google.com/p/badvpn/wiki/NCD" rel="nofollow">http://code.google.com/p/badvpn/wiki/NCD</a> [2] <a href="http://badvpn.googlecode.com/svn/wiki/emncd.html" rel="nofollow">http://badvpn.googlecode.com/svn/wiki/emncd.html</a> [3] <a href="https://gist.github.com/3889970" rel="nofollow">https://gist.github.com/3889970</a>
评论 #4739301 未加载
rgbrgb超过 12 年前
An alternative method of decoupling callbacks is to make heavy use of events within your program. However, perhaps an event is even more like a goto because it doesn't encapsulate state.
评论 #4737515 未加载
nextstep超过 12 年前
Can anybody recommend a way to avoid Callback Hell in Objective-C?
评论 #4736616 未加载
评论 #4735968 未加载
krob超过 12 年前
Amen brotha! I totally agree. Callbacks, especially nested callbacks are a nightmare to debug, and especially to refactor.
jschrf超过 12 年前
The solution to all of this is incredibly simple but for some reason very few people seem to utilize it: State machines.
评论 #4735408 未加载
padobson超过 12 年前
Link seems broken, page fails to load.
评论 #4734944 未加载
exabrial超过 12 年前
So essentially, everything about node.js is wrong? Hmm. Didn't see that coming!
评论 #4734514 未加载
tjholowaychuk超过 12 年前
goto is sweet
martinced超过 12 年前
Why is it that nearly everytime some coding blog writes about something interesting you've got lots and lots of people criticizing the entry and saying, basically, that "the old way of doing thing is just fine, it's just you that are too stupid to understand it".<p>I'm sorry but that's not how it works. I've been coding for 20 years or so and I'm always open to new things. The first time I heard about using immutable objects in Java nearly everybody was laughing at the idea, making fun of it. Nowadays it's the contrary that is true. Same thing for using composition instead of concrete inheritance: everybody was there, ten years ago, saying that there was no problem with Java's concrete (implementation) inheritance. Or checked exceptions. Etc.<p>It's nearly always the same thing: a concept that is not mainstream but that looks very promising is explained in great details and yet people come here, bragging: "You're too stupid to understand ${common way of doing things}, there's no need for ${less commonly used technology}".<p>This really saddens me.
评论 #4734608 未加载
评论 #4733882 未加载
评论 #4733971 未加载
评论 #4734016 未加载
评论 #4734670 未加载
评论 #4735965 未加载
评论 #4736475 未加载
Evbn超过 12 年前
I don't get it. His example just uses "let ... in" syntax instead of putting the next func as an argument to the first. It seemed to be exactly the same thing "deeply nested functions". He just chose not to indent after the "in", and he has a nicer syntax for nested functions.