4 ms·
Actually, that's not a very good argument. The answer to that is "to you, maybe". The better argument is this one: "Must worry about I/O occurring in all functi
by makmanalp 16y ago
Actually, that's not a very good argument. The answer to that is "to you, maybe". The better argument is this one: "Must worry about I/O occurring in all function calls. (They might call wait().) The user needs to make their functions coroutine safe!" I think this is the reason why coroutines are more popular in functional programming languages where side effects are limited by style or by enforcement of the language itself.
- felixge2 16y agoYes, other languages might be more suitable for coroutines. But then again, Erlang is probably a language more "suitable" to high concurrency programming, but node's goal is to make writing scalable networks programs possible for everyone. One might call it the PHP of concurrency : )
- jules 16y agoThat is not a good argument either. If you are going to write your entire IO library in asynchronous style like node.js then you could easily make all IO routines coroutine safe. In fact you have exactly the same problem whether you use coroutines or not. If you have a nice asynchronous program and I call wait in the middle that's going to hurt you in the same way.
- felixge2 16y agoYou're correct, it would not be impossible to write coroutine safe code in node.js. The problem is just that coroutines are not natural in JS, and people will shoot themselves in the foot all the time. Some "features" are better left out to allow a bigger audience to write reliable Software. Your milage may vary.
- jules 16y agoPerhaps, but in my experience using coroutines is easier than using callbacks because coroutines make code look the same as if it was synchronous. readAsync(function(x) { readAsync(function(y) { write(x+y) }) }) vs x = read() y = read() write(x+y) You don't really need to know how to use the full power of coroutines if you just want asynchronous operations. You just need to know that read() may block the current coroutine.
- pmjordan 16y agoYou could even be more explicit about the whole thing, use futures and only allow them to block. The above example would go something like this if the reads can't be executed concurrently: future_x = read(); x = future_x.wait(); y = read().wait(); // shortcut write(x + y); Or something like this if the reads are independent: future_x = read(); future_y = read(); // one of a handful of functions that can "block", all operating on futures: waitForAll(future_x, future_y); write(future_x.get() + future_y.get()); Using futures rather than implicit suspension has the added advantage of being able to pipeline independent reads just as you can with callback-style asynchronous I/O. You can already implement[1] an approximation of this in terms of callbacks, but it doesn't look quite as nice, e.g.: var handler = new AsyncHandler(); // independent, pipelined reads readAsync(handler.cb()); readAsync(handler.cb()); handler.whenDone(function(x, y) { write(x+y); }); It gets substantially uglier than that if the dependencies aren't so straightforward, e.g. A, B & C are independent, D depends on A & B having completed and the last part of the code requires the results from C & D. Futures do much better in that sort of situation. [1] I've built a basic but usable helper for this purpose: http://github.com/pmj/MultiAsync-js/tree/master/src/ http://github.com/pmj/MultiAsync-js/tree/master/src/ I hear the Dojo toolkit contains something similar.
- jules 16y agoExcellent :) Why do you have a separate wait & waitForAll? Couldn't get() wait automatically?
- pmjordan 16y agoI was just throwing ideas out there, not really thinking it through. :) Although you're absolutely right about waitForAll() in that example, there is a point to that sort of function, say if you wanted to add a timeout. Or you could have a waitForAny() function - useful if you only need one of the futures to finish before proceeding. get() vs. wait() is admittedly a question of preference. Personally, I'd keep them separate and even go so far as to have it warn you if you called get() without a wait() or a successful isReady() or so on that future. It keeps the suspensions explicit and the intentions clear. It's a bit like explicit vs implicit transactional systems.