45 comments

[ 3.4 ms ] story [ 97.3 ms ] thread
This works really well. I actually learned some syntax elements I did not know before, like :: for accessing an object's prototype (Array::slice).
Nice tool if you want to convert existing JS code to CoffeeScript. Wonder how stable it is.
Interesting, but has issues with classes.

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've used this to convert some old JS code to CoffeeScript for better maintainability. Usually requires some manual touch-up afterwards, but is still a lot faster than converting by hand.
I like the way

    if (!foo) bar;
gets turned into

    bar unless foo
:)
Am I really the only one who finds it actually a wee bit harder to read when "eyeing" through a lot of code ? It might look nicer, but you read it like "do this, ah no cancel it if that" forcing you to rollback in your head.
I always had that opinion about that feature too. It's present in quite a few languages. I think people like to point out that they can do things that you can't in other languages and end up going ridiculous paths. As if the real power of a programming language could be inferred from it's syntax.

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.

It looks weird at first, but it's great when used like so:

    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.)
The traditional alternative also puts your returns at the beginnings of lines. It just uses a lot more lines.

    if (!err) {
      return x;
    }
    if (condition) {
      return y;
    }
    ...
Not if you do

    if (!err)       return x;
    if (condition)  return y;
I tend to like it if the left-hand-side is overwhelmingly the default code-path, or to keep all assignments aligned (ones with caveats then stick out like a sore thumb).

How do you feel then about things like this?

  variable = if something
      val
    else
      another_val
    end
(insert your personal indentation choice, of course)
This does not cause any "backtracking" when tracing the code execution with the gray interpreter.
>'with the gray interpreter'

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.

(comment deleted)
I'm guessing that he's referring to his brain.
Ahahaha, of course, that makes sense. Thanks, I may have to wake up the hamster in mine :)
Does anyone else find CoffeeScript insufferably unreadable? Why take a basically nice-looking language like JavaScript and bathe it in special forms?
I also find correctly written (i.e. without "bad parts") JS code more clear and readable, with syntax which better articulates programmers intentions. Although it may be that I got used to common JS's idioms and patterns. Anyways I still don't find enough incentive to try to write in CoffeeScript.
Any language is unreadable if you are unfamiliar with it, or languages that share syntax with it. As someone with more of a ruby/python background, I find CoffeeScript incredibly readable. I imagine someone who has only ever learned lisp would find both syntaxes wretched.

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.

I've been programming in ruby last 3-4 years most of my time. Despite of that (or may be just because of that) I still find JS code more clear and elegant for reading/writing (under condition it is well written, i.e. w/o "bad parts"), although it is way more verbose, has camel-case convention which I really dislike etc...
But most programmers are familiar with a structure and layout that is common to other programming languages.
What? CoffeeScript is similar to python and ruby just like Javascript might be considered more similar to C.
I never said they weren't.
I'm not sure what you mean by "they", but your post made it sound like Javascript syntax was better then CoffeeScript because "most programmers are familiar with a structure and layout that is common to other programming languages", which would imply that Javascript syntax is similar to other languages but that CoffeeScript isn't.
I'm sorry, but you are inferring a lot from a simple comment.
I don't think I'm inferring any more than I thought seemed necessary to make sense of your comment given the context. What did you mean by your original comment?
Nah, you just need to learn some languages without C-style syntax.
It fails to return nothing here:

e.onclick = function() { false; } // returns nothing

Translates to:

e.onclick = -> false // returns false

Just out of curiosity, how does one returns nothing in coffeescript?
What's the purpose of the 'false;' statement? I believe CoffeeScript always returns the last line of a function.
The purpose of the false statement is irrelevant. I'm generally not a big fan of perfection in programming, but compilers are one instance it's worth aiming for.
An example.

This 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.

While I totally agree with sid0 that it would be nice for 'academic' reasons if the compiler translated js->cs perfectly, I guess I'm having trouble understanding where this would actually come up as a problem. In my opinion, js functions should always return a value (even if it's just 'this'). Maybe a real code example of where your program would fail because of this?
> would be nice for 'academic' reasons if the compiler translated js->cs perfectly

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
An other good example is constructors; say you have a function like this:

    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 `{}`).
> In my opinion, js functions should always return a value (even if it's just 'this').

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.

I don't understand why this is being downvoted. The compiler's behavior is definitely wrong here, as you showed with your example. This issue could even come up in practice. Suppose you have a checkbox with the id 'cb' in your DOM. Consider the following script:

    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.
Some critique:

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.