Hacker News new | comments | ask | show | jobs | submit login

Very cool post -- looking forward to part 2.

For what it's worth, the syntax foible up for discussion here is intentional. Because CoffeeScript allows you to pass an argument on the right hand side into a function on the left hand side without having to use parentheses, there are several cases where we need to disambiguate:

    f / a /i
Repeated division, or a function being passed a regex with space in it? CoffeeScript treats it as:

    f / a / i
The example in the post is:

    func (arg1, arg2) ->
We disambiguate by saying that if the parentheses are attached to the identifier on the left, then they're part of the function call, otherwise they're part of the argument list as usual. It seems fiddly, but is useful for writing code like this:

    load(url).then (response) ->
      handle response
... as well as code like this:

    reduce(list, {}) ->
      for arg in arguments

This is an important point, and I'm glad I can expand a bit on it here.

Considered as purely a syntactic issue there's not much for discussion. Fix the parser. But! Conceding that method/function application is useful along side the invocation operator `()` (which it certainly seems to be) makes this an interesting semantic issue. That is can two terms mean different things but look "similar"

I have no interest in telling anyone how to build a programming language or that one approach is subjectively "wrong", but knowing that certain term pairs in a language could be ambiguous with respect to each other seems like valuable information. Provided to the creator at the right time it might help with language design.

Eh? This is where I don't follow. What exactly are you recommending should be changed when you say "fix the parser"? Choose the other disambiguation, or simply use an entirely different function literal in the first place?

For what it's worth, this particular ambiguity was discussed as part of the original language design. It was decided that having parentheses for both argument definitions and argument application was useful parallelism, and that function literals shouldn't have to have a "def", "func", "function", or other prefix. From those two ideas:

    # Definition
    (input) -> output

    # Application
... the rest of it falls out naturally.

s/fix the parser/change the parser/, meaning choose not to support both types of invocation.

Both Ruby and Perl have the same challenge, and both solve it by treating the expression differently depending on whether f is a variable or a function/method. As it turns out, you can't actually parse Perl 5 [1], but Ruby can be statically parsed [2], and resolves this ambiguity based on context.

I don't actually know anything about CoffeeScript's parser, and I imagine that it complicates the grammar significantly, but would the same approach not be possible there?

(Personally, I'm quite happy to type parentheses in exchange for clear syntax, and it's these very aspects of CoffeeScript that put me off it: I really find it tricky to follow what's going on when function definitions, function calls, and named parameters are mingled. At least regular JavaScript is syntactically simple, even if I do have to type function more often and worry about this.)

[1] http://www.perlmonks.org/?node_id=663393 [2] http://po-ru.com/diary/ruby-parsing-ambiguities/

[1] is wrong. Perl is defined over a finite memory computer, not a Turing machine that by definition has infinite memory. The Turing halting theorem does not apply.

If you ran perl on a machine with variable size pointers and hotpluggable ports, and added more RAM as needed, you would have enough RAM for any halting program.

I actually prefer this feature to JavaScript. Coffee forces the developer to use parentheses in a meaningful way. Many developers are using outer parentheses in Coffee, similar to Haskell, and I think that provides more clarity.

Realistically in CoffeeScript these versions of the article's examples are far more common, and much less ambiguous:

    doSomething = -> true

    doSomething -> false   or:    doSomething (-> false), otherarg

    doSomething()(-> false)
I feel that extreme flexibility of JS spacing leads to much more ambiguity. Syntax highlighting is in every modern IDE and I never find myself confused. A programmer can write ambiguous code in any language.

I think the amount of controversy over CoffeeScript's syntax is a indicator of its level of innovation.

one common issue i found is in the use of parantheses , around some expressions .

f (c)->2*x , 5 is ambiguous when you read it ( not sure it even compiles ).

or for generator expressions

f(x) if x<0 for x in E

is really ambiguous when you read it.

Maybe CS should be "less smart" and more strict regarding syntax. Because now the task of writing non ambiguous code lies in the hand of the developer. I really think the language should not evolve in a "super language for ninja" like COCO ( which is just too frightening and insane), just keep exposing the functional side of javascript in a better way.

Applications are open for YC Summer 2019

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact