-
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
Tame #1942
Tame #1942
Conversation
I've got a nodejs script that uses child_process.exec() extensively that would be a excellent test case. I'll port it over to this approach on Monday. |
Curious about readability of real-world async coffeescript code. Could you (or someone), please, show compile: (files, callback) ->
async.sortBy files, @sort, (error, sorted) =>
return @logError error if error?
async.map sorted, @map, (error, mapped) =>
return @logError error if error?
async.reduce mapped, null, @reduce, (error, reduced) =>
return @logError error if error?
@write reduced, (error) =>
return @logError error if error?
@log()
callback @getClassName() |
Just doing a simple translation would be the following, however, it seems as if you're leaking compile: (files, callback) ->
await async.sortBy files, @sort, defer error, sorted
return @logError error if error?
await async.map sorted, @map, defer error, mapped
return @logError error if error?
await async.reduce mapped, null, @reduce, defer error, reduced
return @logError error if error?
await @write reduced, defer error
return @logError error if error?
@log()
callback @getClassName()
|
This looks amazing. This new (awesome) syntax clearly doesn't stick very well with CoffeeScript's general behavior of having the JavaScript really similar to the CoffeeScript. The transpiled JavaScript is wildly different looking code--nobody would ever write their JavaScript that way.
Are those comments like Would love some brainstorming on making the output a little more human readable. Similar to how things get stored in _await_f4 = function () {}
_continue_f4 = function () {}
(function() {
(_await_f4())
(_continue_f4())
... etc
}); Awesome work, can't wait to try this out. |
Looks nice! 👍 from me. Added: |
TAME.md should've been a link, so here you go. @paulmillr: I've only read TAME.md, but I figure it'd look like:
There's a slight difference in behavior, though. Every This has left me with the question of how to use Also, I figure any |
+1 |
@stephank good point about autocb only taking zero or one parameter. The current coffee grammar isn't happy with |
@rpflorence thanks the for comments. At the very least regular coffee code without |
My vote is to keep this as a fork until CS gets line number support. I understand the use case of making async code nicer to write in JS, but it seems like a lot of extra complexity for the compiler. I wish the translation continued to happen at the JS part of the stack, and that the only CS hooks were more generic, like the ability to define a custom prefix for statements, or maybe some sort of generic annotation feature. The reason that I'd postpone this until line number support is that I think the CS compiler could benefit from a little bit of rewriting, and the tame features are just gonna make it that much more difficult to do a rewrite. The rewrite that I'd like to see on CS is make the parsing stage a little more generic about building an AST, and then let the code generation piece do more of the reassembly type stuff, such as marrying ifs with else. In general, regardless of line number support, this is obviously a pretty major change to CS, and it seems like we should be conservative about pulling it in. I'm happy to elaborate on the "generic hooks/annotation" idea if that has any resonance with other folks. |
+1 !!!!! |
I want to echo a few of @showell's comments: we must be very cautious with this very large change, and the current relatively small compiler very badly needs a cleanup or a rewrite. I'm going to go through the diff now, paying attention only to proper style or potential bugs. Before I do that, though, @maxtaco: does the syntax used here have any advantages over the syntax I proposed in #1710? I think the syntax from #1710 is more approachable and natural. |
await dns.resolve host, "A", defer(err, ip) | ||
msg = if err then "ERROR! #{err}" else "#{host} -> #{ip}" | ||
console.log msg | ||
cb() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do cb
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm pretty sure func()
is more widely used than do func
, including within the compiler... see e.g. http://coffeescript.org/documentation/docs/lexer.html.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do
is still a new syntax for CS, so it's reasonable that it wouldn't be all over the compiler yet. do
should be used when you're not directly using the value of a function invocation, like when using a function for its side effects. @jashkenas: do you agree? Though this one's kind of different because it's implicitly part of a return
, so either way would be acceptable in my eyes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I still have faint hopes of being able to axe do
eventually... At the moment, it exists as a necessary evil to avoid the ((arg)->)(arg)
pattern, and the ability for it to invoke an arbitrary expression is sort of a consequence of consistency, but I don't think it would be considered good style. This isn't a strong proscription -- just a note for patches against the compiler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do cb
I've been using do
exactly as @michaelficarra describes ('not directly using the value of a function invocation'), especially when an invocation appears at the end of a method, and it really clears up my code in my eyes.
@michaelficarra I like the syntax in #1710, and I'd be open to changing the syntax to make it more Coffee-flavored. But I don't see how it would work with something like a Thanks for taking such a careful read through the code. @michaelficarra or @jashkenas, should I still make these changes/fixes in my branch? |
Yes, if you continue to make changes and fixes in this branch, the pull request will continue to be updated. |
I'll have to look into it once I'm more familiar with the contents of the pull request.
Go ahead and make the changes that I've mentioned so far so that I can delete all those comments and then send you a pull request for anything that's left. I did want to note that the |
Another +1 to the comment from @showell. I'm just a CS user, not someone who's worked with the source. While I would dearly love yield/await in CS (trust me, I'm desperate for something like this), it's more important to my day-to-day development work that CS code be easily debuggable. The harder it is to trace JS errors back to the originating CS code, the less useful CS becomes. @showell : Would these generic hooks be anything like the long-dormant CS extension ideas? See issue #257. I'd love to hear whether CS insiders are open to waking this one up again. |
What I currently like most about CoffeeScript is the comprehensible JavaScript it outputs. I realize using await and defer is optional, but I'd still like to see JavaScript more consistent with what I'm used to seeing from CoffeeScript. Overall I believe the complexity this introduces outweighs what it's trying to fix which isn't necessarily broken. Is there a cheaper price we can pay for this sugar? |
@devongovett, I've enabled issue reporting, didn't realize it wasn't on by default. Thanks for that bug report, I'll puzzle it over. @superjoe30, my original thought on nested awaits is that they should cause a compiler error. I don't think they're very useful and you can always introduce intermediary anonymous functions to be explicit about what's going on. But your example can make sense. Issue the first I'll make two issues over in the branch. |
-1 I've embraced Streamline + CoffeeScript. I prefer that syntax. Adding this to the core of CoffeeScript would be a such a disappointment. |
Is there not something more basic/fundemental that can be added to CoffeeScript that would enable users to build async frameworks upon? It seems to me very much again CoffeeScript to include libs like tame/streamline in the core. I would have thought/hoped that there would be some kind syntax that could be added to enable them though ? |
@weepy To clarify, I'm not arguing for Streamline over Tame. I'm saying that having geared by development to Streamline, with CoffeeScript, and builds that take care of everything, I don't want to see Tame become the default because someone petitioned to have it rolled into the core. |
|
and to be clear I wasn't arguing for either to be in core - just for res.send({ count: User.count!, puzzles: User.puzzles!("today") }) => User.count(function(_0) { User.puzzles("today", function(_1) { res.send({ count: _0, puzzles: _1 }) }) }) or sum = add!(3, 4).length => add(3, 4, function(_0) { sum = _0.length }) Now this is pretty neat, and allows various expression to be used in for i, val in A $.getJSON! val |
I'm starting to see this from the perspective that Iced should be a library. I don't think you'd even have to change the syntax that much, really. |
Hey folks. Just ran across some prior art for this kind of thing -- which I don't recall seeing before -- StratifiedJS' take: https://github.com/onilabs/coffee-script ... if you're interested in this ticket, it's worth a look. |
https://github.com/jashkenas/coffee-script/issues/search?q=stratified |
Stratified definitely predated the original tamejs stuff by some months. I think it's doing CPS conversions and solving the callback pyramid problem. This is a taste issue, but I prefer the iced syntax for two reasons: (1) fewer keywords/syntax changes; (2) callbacks are represented explicitly. That callbacks are represented explicitly gives the ability to get interesting control flow patterns that Stratified accomplishes with further keywords. Take for instance the |
+1, I really like this. |
+1 No comments for six months, weird. Anyway I really feel Iced is a rather elegant and exciting addition to CS. Being a superset, I don't think we'd loose much merging it back in, and we would gain a whole lot. CS is already a fragmentation in the JS ecosystem and would be great to unify the talents in the community. Additionally, having another fork further fragments the tooling, a real issue for users when deciding on suitability (which affects adoption). my humble 2c :p |
You may be interested in looking to #350 |
CS should have modular system instead, so anybody could make extensions to CS that works with each other. But I'd like to see tame here anyway. |
I used IcedCoffeeScript in prototype, and leave several |
+1 |
1 similar comment
+1 |
|
I was the second commenter in this thread. Iced coffeescript does not solve fundamental problem of async js code: composition. The problem is absolutely effectively solved by promises: async.sortBy(files, sort)
.then (sorted) =>
async.map sorted, @map
.then (mapped) =>
async.reduce mapped, null, reduce
.then (reduced) =>
@write reduced You can use promises today and the result code is cute. |
How does this iced code is mapped to promizes? console.log "prepare"
await
for file in files
fs.unlink file, defer()
console.log "done" |
Q.all(files.map (file) -> Q.nfcall fs.unlink, file).then(-> console.log 'done')
Also, consider how your 4-line-coffee-code translates to 20 lines of js. |
@paulmillr While I know, that iced-coffee-script will be certainly slower that your version, For simpler cases coffee-script already provides very pretty syntax for functions. |
Closing for #2762 |
Here's a first stab at a tame pull request, comments welcome. See TAME.md for more details.