-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Haskell-ish left arrow operator, async callbacks #2202
Conversation
I would use the shit out of this syntax, the only thing I'm concerned about is how strongly it assumes that the final argument to the async function is the "standard" callback -- that is, if you had do_request(foo, bar, baz, success_callback, error_callback), you'd be SOL. |
I say yay because i'm pretty tired of async callback shit in my code. And yes, the syntax is a lot more simplier than @maxtaco's. And it doesn't introduce new keywords. Just one question — what about async loops? As for "non-standard" callbacks — I think we should prohibit them. |
Tests don't pass for me. $ ./bin/coffee -bpe 'a <- b p e'
a < -b(p(e)); |
@MichaelBlume That's true. The code already accepts stuff like @paulmillr I think you have to rebuild the parser! I didn't include my .js files in it... It's About async loops, I don't really know how to handle them, you can use |
Thanks, this works now. As for multiple-param callbacks, i'm highly in favor of using rounded parentheses: IcedCoffee:
|
This syntax reminds me of #1710 |
Duplicate of #1704? |
@satyr yea, but I just proposed it and hadn't actually written any code for the problem. |
@paulmillr: well, if this is an implementation of that proposal, and the proposal was turned down, why should the implementation be accepted? I think it still might be appropriate to have another discussion about this feature on the grounds that it's probably good to periodically revisit this topic; it is extremely important to some people and would be a huge feature for CS if it could be done right. |
@michaelficarra I agree with you, let's discuss the feature, especially cons of it. /cc @showell |
This is really the first unobtrusive, simple implementation of this kind of feature that I've seen yet. Most importantly: if you hand me a page of code using this syntax, I can easily work out what the Javascript will look like. |
@MichaelBlume especially when compared to IcedCoffee which compiles var data, error, __iced_deferrals, __iced_k_noop,
_this = this;
__iced_k_noop = function() {};
__iced_deferrals = new iced.Deferrals(__iced_k, {});
readFile(__iced_deferrals.defer({
assign_fn: (function() {
return function() {
error = arguments[0];
return data = arguments[1];
};
})(),
lineno: 0
}));
__iced_deferrals._fulfill(); and requires iced runtime to work. |
@paulmillr A lot of that generated code is there for features that aren't covered in this new proposal, like async-aware stack-traces and parallel async calls. We use these features frequently in the app we're building. I would argue this proposal introduces one new keyword, Finally, if you want to handle rewriting of loops properly, and you don't get runtime support from V8 and/or node and/or your browsers of choice, you need to part with the notion of simple code output. |
I'm afraid that it isn't particularly clear what's going on here at all to me. does
Would that also result in 3 nested deferrals? If so, then the await/defer model is far more exciting to me than this minor sugar for your initial case
Am I right to say that all you've actually saved is a bit of indenting for the trivial case? Unless the syntax is meant to automatically figure out what it can and can't fire in parallel (which seems a daunting task, and ignores cases where you'd like to intentionally not fire things in parallel), then for me this is so trivial as to unfortunately constitute a waste of the interesting Beyond being limiting that it only works where the callback is the last argument, it's also very unintuitive to me to see the last argument missing in the call to Also, pretty much +1 on everything @maxtaco said. |
I believe that the main point of I think it's just like postfix About this being a duplicate, I had no idea. I tried searching but couldn't find those other issues. It's just something I thought that would be cool, and hacked in a few minutes. |
To steal some of IcedCoffee's keywords, here's an attempt at writing multiple callbacks that resume at the same time, implemented as a pure Coffee library:
Assuming "defer()" queues callbacks, and "await(cb)" waits for these to finish, and returns all arguments in defer's calling order. This also gives you the benefit of being able to move the callback:
|
@timcameronryan that's an interesting take, but that's really only the start of it.
It's also pretty badly unDRY: your a, b, c order is a repeat of the order of the defers: changing the defers requires you to reorder that list. That invokes all the ugliness of maintaining an unwieldy printf statement. That defer and await have to deal with some global data there too, which could lead to bugs starting a long way off from where they break things, say removing an await, but missing one of the defers leading up to it, leaving it in the await stack for the next guy, thereby throwing off the count. I'd be more inclined to say that in a pure coffescript lib, you might see:
Which looks hideous, because to make this a nice sealed block of stuff:
The proposed sugar, I suppose could be applied to produce:
But that's hardly attacking the problem, imho. The proposed syntax just barely shuffles things around with minimal benefit, and you'd still have to write different versions for dealing with cases where the number of deferred items was unknown. The problem that the iced coffeescript syntax solves for me is that the await keyword actually produces a block in which:
Beyond that though, they've actually started tackling bigger problems like debugging who called the deferred function in the first place when things go wrong, which is where the real area of interest for me is. Those things definitely require that the concept of a callback be more integrated into the language than just a syntactic slight of hand. I guess what I'm saying is that while you reckon this is a problem on the postfix
As for what that produces in javascript terms, well I suppose that's negotiable. Looking at iced's output, I have no trouble buying why it's done what it's done: it broke down the problem step by step and has had to construct temporary functions and objects to translate what you've asked for into javascript, while adding its debugging features along for the ride. If you look at it, in principal it's just a grander, more flexible, more complete vision for what this pull request attempts to do. |
@timcameronryan IMO, using I think the selling point of the But since we're having fun bikeshedding and the
O_O |
@csubagio @shf I agree. My point wasn't to poorly reimplement IcedCoffee, but see what complex behaviors could be trivially implemented when enabled by the |
@shf so with |
@meisl Well, this is why I think that the |
I'm afraid that -- while it's great to revisit these issues from time to time -- this current conversation mostly re-treads earlier attempts to add simple async sugar to CoffeeScript ... and suffers from precisely the same issues, some of which @maxtaco mentions. For a more complete version of this sort of thing, see what Kaffeine does with http://weepy.github.com/kaffeine/docs/unwrapping_async_calls.html |
Hello!
This is just a proof of concept for this idea I had. It's a bit like IcedCoffeeScript, but instead of using async/defer, it uses the
<-
operator to turn sequential code into CPS, just like Haskell. I think it looks "cleaner" and fits more with the rest of CoffeeScript, plus,<-
makes a lot of sense, since it's the opposite of->
;)This is nowhere as advanced as @maxtaco 's fork, and the code quality isn't that good, but since it's just a proof of concept, here it goes...
So, it turns this:
Into this (generated by CoffeeScript):
As I said, it's not production-quality code. Particularly, the algorithm that searches and replaces nodes downward on node.coffee is hack-ish and has a lot of duplication (the getSiblings should be on Base), but I wanted to keep it short, so...
Oh, you have to rebuild the parser for it to work, btw...
So, what do you folks think? Yay? Nay? Way too close to monad-land?
Thanks!