Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Scope for self-referencing functions #1188

Closed
TrevorBurnham opened this Issue · 5 comments

4 participants

@TrevorBurnham
Collaborator

Someone posted a StackOverflow question this morning that pointed out that

init = ->
  ...
  init = -> doSomethingElse()

compiles to

var init;
init = function() {
  var init;
  ...
  return init = function() {
    doSomethingElse();
  };
};

That inner var init; declaration surprised him, and it surprises me as well. It's a weird exception to normal scoping rules, isn't it? And as a practical matter, enabling functions to overwrite themselves is quite useful.

The workaround is simple, of course: Just add init = null before the code.

@michaelficarra
Collaborator

Yep, that's how our scoping works. We don't pay attention to variable declaration hoisting rules. Since init had not yet been defined at that point, it enters the scope inside the function as well. This is no different than your issue #1121. It's a little weird coming from an experienced JS programmer's background, but after talking with jashkenas about it when #1121 was open, I feel that it's right.

@TrevorBurnham
Collaborator

I mean, it isn't really the same as #1121 (though "fixing" that issue would also fix this one). As you say, it's the way JavaScript works:

init = function() {
  // "init" lets this function reference itself
}

But more importantly, it feels antithetical to CoffeeScript's ethos to allow people to use the same name to refer to two different variables even on the same line:

func = -> func = (-> 'this is weird')

I don't see any problem with making a special case for assignments made on the same line as a function definition to be processed for scoping purposes before the inside of the function is. Is there something I'm overlooking?

@michaelficarra
Collaborator

I think that suggestion would be even more confusing. At least with the way it is right now, it is very consistent. And how does this differ from #1121? You were asking for variable declaration hoisting. Now you're asking for hoisting only when declaring with an assignment to a function.

Remember,

var init = function(){ return init; }

is interpreted in JS as

var init;
init = function(){ return init; }

and you would like CoffeeScript to behave the same way (except only in some certain situations, apparently). That's hoisting.

@satyr
Collaborator

Declaring the variable before compiling RHS would fix it, which is reasonable considering = evaluates the LHS first:

$ coffee -e '[][console.log 1] = console.log 2'
1
2
@jashkenas jashkenas was assigned
@jashkenas jashkenas closed this in f3f34e9
@jashkenas
Owner

@satyr and @TrevorBurnham are right -- this is a bug. I've fixed it in the previous commit by reordering the variable declaration and RHS compilation.

@satyr satyr referenced this issue from a commit in satyr/coco
@satyr satyr addressed jashkenas/coffeescript#1188 4b1e3ff
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.