CoffeeScript for loop get iterator var

2019-09-04 20:24发布

In coffescript I have

arr = ["a","b","c"]
for i in [0..arr.length] by 1
  if (sometimesTrue)
    arr.pop()
    i--

But it is translating it to this:

var arr, i, _i, _ref;

arr = ["a", "b", "c"];

for (i = _i = 0, _ref = arr.length; _i <= _ref; i = _i += 1) {
  if (sometimesTrue) {
    arr.pop();
    i--;
  }
}

You can see that this loop uses a _i as the reference rather than i so my i-- doesn't really do anything.

Since in this loop, the length of the array changes, I sort of need to figure out how to handle this... Is there any way to do this with a for loop? Or do I need to switch to a while?

4条回答
Emotional °昔
2楼-- · 2019-09-04 21:08

CoffeeScript will compute the loop bounds once and you can't reset the calculation so changing the array while you're iterating over it will just make a big mess.

For example, this:

f(i) for i in [0..a.length]

becomes this:

var i, _i, _ref;
for (i = _i = 0, _ref = a.length; 0 <= _ref ? _i <= _ref : _i >= _ref; i = 0 <= _ref ? ++_i : --_i) {
  f(i);
}

Note that the number of iterations is fixed when _ref is computed at the beginning of the loop. Also note that i will be assigned a new value on each iteration so any changes you make to i inside the loop will be ignored. And, note that looping over [0..a.length] does a.length+1 iterations, not a.length iterations; [a..b] produces a closed interval (i.e. contains both end points), [a...b] gives you a half-open interval (i.e. b is not included). Similarly, this:

f(i) for i in a

becomes this:

var i, _i, _len;
for (_i = 0, _len = a.length; _i < _len; _i++) {
  i = a[_i];
  f(i);
}

Again, the number of iterations is fixed and changes to i are overwritten.

If you want to mess around the the array and the loop index inside the loop then you have to do it all by hand using a while loop:

i = 0
while i < arr.length
  if(sometimesTrue)
    arr.pop()
    --i
  ++i

or:

i = 0
while i < arr.length
  if(sometimesTrue)
    arr.pop()
  else
    ++i
查看更多
Juvenile、少年°
3楼-- · 2019-09-04 21:14

Using indices in coffeescript is quite unnatural.

I think that what you want is something like :

arr = ["a","b","c"]
arr = (i for i in arr when ! sometimeTrue )

I think that you should read the following topic "Loops and Comprehensions" at http://coffeescript.org/

查看更多
成全新的幸福
4楼-- · 2019-09-04 21:16

Modifying the array you're looping over rarely does what you want in languages with for ... in ... constructs. What you're really looking for is a filter. Many javascript implementations have a filter function attached to the array prototype:

arr = arr.filter((member) -> !sometimesTrue)

If you can't count on this, you can use a similar CoffeeScript construct:

arr = (member for member in arr when !sometimesTrue)
查看更多
\"骚年 ilove
5楼-- · 2019-09-04 21:18

Sometimes it helps to take a walk, maybe in real fresh air in the woods, maybe in front of the house with a cigarrette (though your wife might hate the smoking) ... Somtimes it even helps to talk to the rubber duck some uber-geeks have on their monitors. And sometimes it plain and simple helps to attack the simple things from a different angle. arr = ["a", "b", "c"]

for i in [0..arr.length]
  if (sometimesTrue)
    arr.splice i, 1
  else i++

EDIT: As seen in the comments below I was missing something here. I is indeed not ignored at all, how could I've thought that in the first place?

查看更多
登录 后发表回答