3 ms·
This is a fork of the language, not an official feature. It’s as if you wrote your own version of JavaScript that trampolines function calls and performs tail-c
by raganwald 15y ago
This is a fork of the language, not an official feature. It’s as if you wrote your own version of JavaScript that trampolines function calls and performs tail-call optimization. You still need to go through the social process to get your ideas into the main “trunk.” Selling people on adopting your fork might be one way to get everyone excited about the idea.
That being said, right up front he explains the two reasons why this is a departure from CoffeeScript’s core philosophy: `await` and `defer` are changes in the semantics of JavaScript, and not surprisingly, code written in IcedCoffeeScript no longer compiles into more-or-less recognizable JavaScript.
Modulo syntax and sugar, CoffeeScript is JavaScript with some minor changes to the AST (such as soaking up nils with the Elvis operator). IcedCoffeeScript is another language that evolved from JavaScript and transpiles to JavaScript.
Before adding such features willy-nilly to CoffeeScript, folks need to be comfortable walking away from a core value. I’m not saying that’s a bad thing, but it’s a problem related to the Innovator’s Dilemma: To embrace this new value, CoffeeScript will have to alienate some portion of its user base that value compiled JavaScript that is easily recognizable to anyone who has read the CoffeeScript source.
- chc 15y agoAs a user, you don't really need to walk away from anything. There isn't any difference between Iced CoffeeScript output that doesn't use await and vanilla CoffeeScript output. You could literally switch out somebody's name-brand CoffeeScript for Iced and he'd never know the difference unless he had a function called await. It's purely an ideological concern, not a practical one.
- raganwald 15y agoYou’re preaching to the choir! But one objection we will both encounter repeatedly is that if a language supports feature X, and you work on a team/inherit code/use libraries, there will always be people who don’t want to use feature X but wind up dealing with it any ways because someone else used it. So the naysayers will claim that if it’s added to the core language, it’s only a matter of time before they wind up dealing with it whether they like it or not. Given the way that most Ruby users have to live with monkey-patching in Ruby whether they do it themselves or not, I fully expect that if await and defer are added to core CS, there will be libraries or CommonJS modules that use it and presto, you may find yourself looking at some of its output in the debugger one day. I’d rather use the feature myself and benefit from it, but I can accept what the luddites are saying even if I don’t end up coming to the same conclusion about whether the feature should be added or withheld :-) UPDATE: I recall being told that tail-call optimization should not be added to certain languages because it encourages programmers to write recursive functions that are “hard to read.” You might argue that if you never write recursive functions, why should you care? But people do care.
- drostie 15y agoMaybe. Tail recursion optimizes itero-recursive algorithms, turning them into iterative algorithms by eliminating the overhead. Confused? Here are the iterative, recursive, and itero-recursive ways of writing the factorial function: function fact_r(N) { return N <= 0 ? 1 : N * fact_r(N - 1); } function fact_i(N) { var acc = 1, i; for (i = 1; i <= N; i += 1) { acc *= i; } return acc; } function fact_ir(N, acc) { acc = acc || 1; // default value of acc return N <= 0 ? acc : fact_ir(N - 1, N * acc); } So the accumulator variable becomes an argument variable which may have to be separately initialized. The key feature which makes something optimized for "tail calls" is that when f(something) wants to recurse, it returns f(something else). In other words, certain conditional logics can happen, but don't leave an operation like the "n " in "n recurse(n - 1)" on the stack or else you can't get rid of the function call. It's not even a special optimization -- basically you can move one line in the compiler a couple steps ahead of where you might have automatically written it, and it suddenly treats iteration and tail-recursion the same. So that's the difference. If you can understand fact_ir, which does the iterative idea in a recursive syntax, then you can understand tail recursion.
- 6ren 15y ago> code written in IcedCoffeeScript no longer compiles into more-or-less recognizable JavaScript So this is a more fundamental fork than first appears... And it explains why it includes debugging information (loading up the code examples reveals artifacts like lineno: 6 in the output JavaScript). I recall a debate about debug info, turning on the values you note. Can't find it right now. (though, apparently extra-linguistic Source Maps are being introduced into browsers http://news.ycombinator.com/item?id=2862629 http://news.ycombinator.com/item?id=2862629) Personally, I think "clean JavaScript" is the right adoption strategy, for now, in a JavaScript-dominated world. When CoffeeScript has native browser support, that value can be dropped (it might not happen: MS supports VB, Google supports Dart... even if Mozilla supports CS, the others mightn't). Finally, I don't think the resulting JavaScript is that hard to understand - you can easily see the correspondences with the source. However, it's the thin-edge of the wedge. What changes will be added next?