jashkenas/coffee-script — Issue #2152: Named functions
Author: adrusi
Created: 2012-02-28 01:26:45+00:00
State: open

Currently, coffeescript does not allow for named functions, it only allows the binding of unnamed functions to variables, which has slightly different semantics, and a difference in functionality. I'm sure that this has been brought up before, but I might have something new to add.

In javascript, the following will output "foo bar":

function foo() {
console.log(bar());
}

foo();

function bar() {
return "foo bar";
}

This output is not possible from coffeescript, instead, we do this:

var foo = function () {
console.log(bar());
};

foo();

var bar = function () {
return "foo bar";
};

Which, is an error because `bar` is not defined yet when it is called.

It's actually very useful to be able to use functions before they are defined in the code, especially for functional-style javascript, but the functionality is simply not present in coffeescript.

It's also worth noting that named functions as expressions rather than statements make for more convenient recursion.

I'm not completely sure about the syntax, but I propose and addition to the language to allow for this. In this feature request, I'll use the long and long fat arrow (`-->` and `==>`).

The first code example could be rewritten in coffeescript like this:

foo -->
console.log bar()

foo()

bar --> "foo bar"

It's tempting to allow paren-free syntax, but that would create some ambiguous cases

map f, ns --> # awesome! no parenthesis!
if ns.length is 0
[]
else
[f ns[0]].concat map f, ns.slice(1)

map someFunc --> ... # is that declaring map(someFunc) or calling map on a function with no arguments (I know map makes no sense without an argument)

To parse this, when the `-->` token is encountered, it looks back until the most recent identifier, followed by a space, followed by a valid argument token.

It would also be very cool to have this syntax work inside objects and classes, this way we could have:

class Foo extends Object
constructor -->
# ...