JS 2 CoffeeScript Compiler
js2coffee.org
js2coffee.org
https://github.com/rstacruz/js2coffee/blob/master/lib/js2cof...
e.onclick = function() { false; } // returns nothing
Translates to:
e.onclick = -> false // returns false
fn = -> returnThis could be any statement evaluating to false.
Coffee script returns the result of the last statement. Javascript don't. So, failing to take this into account produces coffeescript that do not have the same behavior than the original javascript.
This is particularly important for iterators that return false for stopping iteration. Or for DOM event handlers that return false for stopping the propagation of the event.
You should expect this from a compiler, actually
> In my opinion, js functions should always return a value
Sounds wrong
> real code example of where your program would fail because of this?
Simple:
// That's perfectly fine; why would I return anything from this ?
link.onclick = function() {
doSomething();
};
// Now, translated in coffeescript:
link.onclick = ->
return doSomething(); // if this returns false, the "click" event is canceled function MyClass(x){
this.x = x;
}
In Coffeescript this translates to MyClass = (x) ->
@x = x
`x` is returned; and if you return something from a constructor, something is returned instead of the constructed object (`new MyClass({})` returns `{}`).Yeah, well, you know, that's just, like, your opinion, man.
It's perfectly valid for JavaScript functions to not return something. Your opinion about always returning something (which I agree with, btw) is only a personal stylistic preference, and from the code I've seen in the wild, it's not really that widespread.
As fooyc points out, the behavior of onClick events in the DOM changes depending on what return value is received. As I understand it, when an onClick executes a script, the truthiness of the value it returns determines whether the event continues to bubble up the DOM after the onClick has executed. At a guess, 75% of the onClick handler functions I've seen in the wild do not return a value; whether they realize it or not, all of those handlers implicitly rely on the appropriate truthiness of not returning a value for the rest of the page to behave correctly. Suddenly giving those functions a return value, especially one the developer didn't intentionally choose and didn't expect to have any effect, could cause quite a bit of unexpected behavior.
This also seems like an easy issue to address. No return statement in the JavaScript? Add an empty return in the CoffeeScript.
var list = [true, false, true, true, false];
document.getElementById('cb').onclick = function() {list.pop();};
When the checkbox is clicked, it should remove the last item in the list,
then put a checkmark into the box. Run this through the Js2coffee compiler
and you will get list = [ true, false, true, true, false ]
document.getElementById("cb").onclick = -> list.pop()
Run this back through the CoffeeScript compiler to get: (modified slightly
for brevity) var list = [true, false, true, true, false];
document.getElementById("cb").onclick = function() {return list.pop();};
Notice that it now returns the result of list.pop(). Since the last item in
the list is false, this will prevent the default browser behavior, so the
checkbox will not be checked when it is clicked the first time. if (!foo) bar;
gets turned into bar unless foo
:)Don't get me wrong, I like coffee script and I find the tool linked on this thread quite useful, but come on... rewriting all the 'ifs' as 'unless' jut because you can looks pointless and silly to me. Just my opinion.
return x unless err
return y if condition
...
return z
Keeping all of your "return"s at the start of the line makes it much easier to see, at a glance, what the possible return values of your function are. (And, of course, when you see a "return" in the middle of your function, you know there must be a condition attached.) if (!err) {
return x;
}
if (condition) {
return y;
}
... if (!err) return x;
if (condition) return y;How do you feel then about things like this?
variable = if something
val
else
another_val
end
(insert your personal indentation choice, of course)sorry, ya lost me there. Are you referring to a language interpreter? In that case, which one?
The only difference I can see for interpreters is that it necessitates parsing the entire line before acting, which all but the most highly-tuned (and designed for this purpose) interpreted-languages probably already do.
I tried with a couple lengthier bits of code that JSLint happily eats and I get an "Illegal token" error with no coordinates or anything to help me. Ah well.
Also not very happy with the custom scrolling in the source text area -- my mouse wheel is set up to scroll 6 lines per wheel click. The source text area scrolls approximately 1.5 at a time.
Kudos to the author!
1: https://github.com/Shopify/batman/commit/6b421b32c2d28bc7e41...
I turned that find function into a class with a method, and converted it back and forth and the JS->Coffee came out oddly. Definitely not nice CoffeeScript, even if it worked.
I do think, however, that many of the ruby-ish syntax tweaks are more expressive once you get used to them. That is, I learned C-like syntaxes before I learned ruby and I still find I'm able to parse ruby-like code much faster than c-like code. There is more to learn in terms of symbols, constructions, but once you know them, they communicate more information faster.