And thus does the javascript ontogeny finally finish recapitulating phylogeny, and we arrive at the inevitable end point: The Erlang/Go way is the best way to do this stuff after all.
If you still end up using Javascript at the end of the process, hey, great, go nuts, but after years of swaggering optimism in the JS community about how somehow their stuff was so much better than anybody else's despite "event-based code" being extraordinarily well-trodden ground since the 1990s (as in being the default programming model for all serious code and entire major dominant operating systems), it might be worth people taking a moment to consider whether some more listening at the beginning of the process might have cut some years off this journey of discovery. The Javascript community has not been leading the charge of writing asynchronous code... they just caught up.
The erlang/go concurrency model is the most overrated paradigm ever.
Sure, the abstraction isn't leaky... Because there is barely an abstraction at all. Synchronizing state between independent processes is a very real, very unfun problem when all you have is the actor model.
For what it's worth, all of Facebook.com fetches its data with async/await (effectively promises+data) which is a nice sweet spot and a lot better to work with than actors.
Go uses CSP concurrency, which is distinct from the Actor model. They're often conflated since the difference is small, but the distinction is relevant here because it directly addresses your complaint. Namely, synchronization is much easier in CSP since communication is synchronous, so you don't have to build additional abstractions for syncing on top of your asynchronous message passing.
That was not a mean-spirited comment, especially if you imagine someone with a bit more experience seeing the same thing recur needlessly. Grouchy with a touch of get-off-my-lawn, yes. Mean-spirited, no.
Over-exuberance sometimes requires admonishment, especially when there is such a colossal waste of energy and effort like in the JavaScript "community" (OP's word, but still...). If JavaScript programmers spent more time listening and reading and less time posting "so I wrote my own" blogs we might have had things like Reactive libraries for JavaScript years ago.
Throwing a word like "hate" around tells me you're likely too young to really understand what that means.
Also, you picked on his tone and let the Go comment slide? Really?
2. Promise.prototype.bind
4. You can put try / catch / finally anywhere. It doesn't have to be in the end, but it does have to be close to what you want to wrap (just like any other try / catch).
Coming form a large node project where I have been spending the better part of my waking hours for several weeks closing memory leaks caused by holding onto closures indefinitely, I would advise against the sort of meta programming advised in this article.
Indeed, I'm surprised the author doesn't know about them (or atleast doesn't mention them). Especially since even the async-await strawman (the first thing you'd find when googling for async-await in JS) demonstrates an implementation via generators...
https://github.com/srikumarks/cspjs - The readme has benchmarks from bluebird generators. It is only 74 ms slower than the sweet.js solution. So the author knows.
Generators are up there with the let keyword in the list of "things I wish I had (native) access to already" because there's just so many use cases for them. This is definitely one combination I haven't thought of before though, so thanks for bringing it up!
They work together beautifully, i wrote this little prototype/promise helper for node (https://github.com/icodeforlove/node-promise-object#deferred...). And it removes all of the boiler plate associated with using promises, and generators (if you're ok with argument stuffing).
Generators dont give you async programming capabilities.You need a library that actually wraps generators into coroutines,and then wrap async functions into "thunks" to make it work.
yes generators can help you control the flow as you do async programing, but you can't use generators to do something like an ajax function which gives you an async value, you'd need promises or something for that, generators allow you do use those async function is a more natural way.
JavaScript and C++ have a similar problem. There are so many ways to do so many things, that the result is endless stylistic fragmentation and tons of library bloat. C++ is getting better as C++11 introduces standard ways to do things like lambdas, tuples, etc., but JavaScript is obviously still in its experimentation phase.
IT's very easy to criticise a technology when you're not using it correctly. Please consider reading the Bluebird usage examples, what you're doing is _definitely_ not the recommended usage.
You can achieve what you're doing without any macros, with better throw safety, better debugging traces and more.
It seems like there's two ideas here: new error handling syntax, and new asynchronous task handling syntax. About asynchronous tasks: I think many people here might be interested in taskjs which combines Promises and ES6 generators (http://taskjs.org/) and the similar ES7 async function proposal (http://wiki.ecmascript.org/doku.php?id=strawman:async_functi...). You can use await on a function that returns a promise and write code just like the code in this article (besides the error handling stuff). In basic sequential code, you never have to call .then() on a promise, but you're still able to dive down and do that if you have some non-linear asynchronous code that requires it.
Yes but No.I personally think macros are the "root of all evil". Because they just make languages unreadable. That's one thing to have a complete different language that compiles down to JS,but as soon as you introduce macros is your code you make it harder to understand and document.I'm glad it works for you,but in my opinion the use of macros should be banned.While limited to nodejs, I personally think fibers are better alternative.
4. I actually think that it makes promises elegant. You can chain 20 then and have a single catch in case things are wrong,but you need to adjust the logic accordingly.Using different Error "classes" and checking the type is usually what I do.
I still believe promises are an elegant way to deal with async programming,and ES6 lambdas will make them even less painfull.
I'm not sold on generators for async programming strangely ,for multiple reasons(lack of support in browser land,especially on mobile).
EDIT: macros are fine in LISP likes because it's not like these languages have a complex syntax. And in C,well you cant program without them. My point is javascript has enough features to make macros unnecessary.
I don't think you understand the ability for macros to make code more readable.
"However, as we confront increasingly complex problems, we will find that Lisp, or indeed any fixed programming language, is not sufficient for our needs. We must constantly turn to new languages in order to express our ideas more effectively. Establishing new languages is a powerful strategy for controlling complexity in engineering design; we can often enhance our ability to deal with a complex problem by adopting a new language that enables us to describe (and hence to think about) the problem in a different way, using primitives, means of combination, and means of abstraction that are particularly well suited to the problem at hand."
I've used C a lot, and while you do need macros sometimes, IMHO it's best to use them as minimally as possible. So I'm in agreement.
lisp/scheme have macros that understand the structure of the code in a more fundamental way; they're more a feature of the language than a pre-processing step.
This seems overly restrictive. Especially when, at a base level, macros should be easier to explain than some alternatives. It is quite literally, "take this and replace it with that."
Don't get me wrong. They can hurt a codebase such that it is not readable anymore. But you know, functions can do similar. Heck, for some code basees, the same thing.
I'd argue that sweetjs actually changes JS syntax,which is not the case with some other languages that have macros. If JS had Ruby's blocks, there would be no need for sweetjs. But I've heard TC39 wants to introduce macros in the future,so you might have them anyway...
Ruby certainly has first-class functions. Not only can you pass "functions" around as lambdas or procs, you can also detach and re-atach methods from a class or object at runtime.
From the wikipedia:
"Specifically, this means the language supports passing functions as arguments to other functions, returning them as the values from other functions, and assigning them to variables or storing them in data structures"
All of these things are certainly possible in ruby, see [0] fizzbuzz in the lambda calculus in ruby
"The identifier of a regular "function" in Ruby (which is really a method) cannot be used as a value or passed. It must first be retrieved into a Method or Proc object to be used as first-class data. The syntax for calling such a function object differs from calling regular methods. Nested method definitions do not actually nest the scope."
You can certainly make the case that Ruby has first-class functions, but they don't feel very first-class in practice.
"Bare" Ruby blocks are called differently from calling methods (yield).
But the moment you name a block (pass it to a method with a named block argument) or create one with "proc" or "lambda" or "Proc.new", the form you get access to it in is a Proc object, and calling it is a method call (ob.call).
The distinction is quite pointless, other than as an implementation artefact for MRI, as there shouldn't be any obvious observable differences in behaviour between a bare block and a Proc (in my "eternally in progress and not very functional yet" Ruby compiler, all blocks are in fact Proc instances, though if you can tell, it's a bug)
It's interesting to me that people seem to be trying to bridge Promises with CSP. Why aren't more people investigating the more straightforward async/await transformation that the C# compiler does? CSP just seems like one transformation too far.
async/await is trivial to mimic with yield - run the outer-most generator in spawn, use yield* with "async" methods, and use yield with Promise-returning methods. Projects like Regenerator already know how to convert yield to straightforward JS. So you already have the transformation the C# compiler does.
async/await is an upcoming JS feature that actually is kind-of supported by Bluebird when combined with generators. The author just didn't know about it (I guess) and reimplemented it via macros.
A bit off topic but in the context of promises and Angular, I love the ability to set a set a promise for the timeout parameter. This is super valuable 'cause it lets me manually cancel any request instead of waiting for a response or timing out via time.
If you'd like - we have a $q decorator in our code base that adds `.timeout` to promises and allows you to cancel them if the timeout expires (just like in Bluebird, from before we used Bluebird with Angular). Let me know if that's interesting to you and I'll put it on GH.
You can pass a promise into an $http request as a parameter. If you hold on to this promise and resolve it before the request returns, it cancels the request.
I assume the grandparent is talking about functions in Angular that take in a numeric timeout parameter and wants them to take in Promises instead, so he can reject the promises to signal that he wants to cancel the operation.
There seem to be two major ideas going on here: CSP, and modifications to try/catch syntax. It would be easier to understand the former without the latter.
If you still end up using Javascript at the end of the process, hey, great, go nuts, but after years of swaggering optimism in the JS community about how somehow their stuff was so much better than anybody else's despite "event-based code" being extraordinarily well-trodden ground since the 1990s (as in being the default programming model for all serious code and entire major dominant operating systems), it might be worth people taking a moment to consider whether some more listening at the beginning of the process might have cut some years off this journey of discovery. The Javascript community has not been leading the charge of writing asynchronous code... they just caught up.