Variables inconsistently masked inside of `do` #1403

Open
ghost opened this Issue May 30, 2011 · 5 comments

3 participants

@ghost
# The variable `masked` is redeclared inside of the anonymous
# function created by `do`.
for dummy in [0...1]
  masked = 10
  do -> alert masked = masked + 1
alert 'a line needs to be here to trigger the issue'
# The variable `notMasked` is *not* redeclared. The only
# difference is that `+=` is used instead of simple
# assignment.
for dummy in [0...1]
  notMasked = 10
  do -> alert notMasked += 1
alert 'a line needs to be here to trigger the issue'

Here is the JavaScript generated by the first (broken?) example:

var dummy, masked, _fn;
_fn = function() {
  var masked;
  return alert(masked = masked + 1);
};
for (dummy = 0; dummy < 1; dummy++) {
  masked = 10;
  _fn();
}
alert('a line needs to be here to trigger the issue');

Here is the JavaScript generated by the second (working?) example:

var dummy, notMasked, _fn;
_fn = function() {
  return alert(notMasked += 1);
};
for (dummy = 0; dummy < 1; dummy++) {
  notMasked = 10;
  _fn();
}
alert('a line needs to be here to trigger the issue');

I believe I've reduced the issue to its simplest form, though I could be wrong.

The following prevents the masking from occurring:

  1. Changing the for loop to an if or a while loop
  2. Removing the line immediately following the for loop
  3. As demonstrated, changing the simple assignment to a +=
  4. Assigning the masked variable before the loop
@TrevorBurnham
Collaborator

Thanks for the report, esk. I've been trying for a while to get that _fn function inlined (see issue #960), which should make the scope issues trivial...

@TrevorBurnham
Collaborator

Worth mentioning that this isn't strictly a do-specific issue; you get the same results if you change

do -> alert masked = masked + 1

to

(-> alert masked = masked + 1)()

Also, the += thing you mentioned is actually the result of Jeremy's decision that compound assignment operators shouldn't create scope... see #1122. So if you were to write

masked += 1

in a file and masked weren't assigned anywhere else, it would actually modify the global masked. This is the only exception to CoffeeScript's rule that globals must be referenced explicitly (e.g. as window.masked) to be modified.

@ghost

Thank you for that information, TrevorBurnham.

If the behavior of += is intentional, should I change the issue's two examples and description to indicate that the inconsistency only lies in the first, second, and possibly fourth list items?

The following prevents the masking from occurring:

  1. Changing the for loop to an if or a while loop
  2. Removing the line immediately following the for loop
  3. As demonstrated, changing the simple assignment to a +=
  4. Assigning the masked variable before the loop

I don't quite know the proper etiquette for editing things after someone has responded.

@TrevorBurnham
Collaborator

I'd just leave it unedited, since it's tangential to the point of your post (and not incorrect, really).

@michaelficarra
Collaborator

I don't quite know the proper etiquette for editing things after someone has responded.

I will usually edit my posts after someone has replied only if it doesn't change the meaning of their reply. I'd hate to put words in someone else's mouth, so I would only edit parts that are not related to their comment. There are exceptions, though, like errors in example code. Just note with an additional reply that you fixed it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment