33

Background: I'm trying to convert some JavaScript code which uses the the Crossfilter library with D3.js data visualization library into CoffeeScript.

What is the best way to convert a JavaScript forEach loop/function into CoffeeScript?

Here's the JavaScript code:

// A little coercion, since the CSV is untyped.
flights.forEach(function(d, i) {
    d.index = i;
    d.date = parseDate(d.date);
    d.delay = +d.delay;
    d.distance = +d.distance;
});

Can CoffeeScript do an in-line function inside a loop? Right now I'm guess I need it broken out into a function and loop:

coerce = (d) ->
     d.index    = 1
     d.date     = parseDate(d.date)
     d.delay    = +d.delay
     d.distance = +d.distance

coerce(flights) for d in flights
0

3 Answers 3

48

Use a comprehension:

for d, i in flights
  console.log d, i

The code above translates to:

let d, i, _i, _len;
    
for (i = _i = 0, _len = flights.length; _i < _len; i = ++_i) {
  d = flights[i];
  console.log(d, i);
}

so you can see d and i are what you want them to be.

Go here and search for "forEach" for some examples.

Finally, look at the first comment for some more useful info.

Sign up to request clarification or add additional context in comments.

1 Comment

Just so OP knows, this is not equivalent to the JS code. It'll iterate over undeclared properties, whereas a forEach won't. Also, it doesn't create a new closure during each iteration, so if there are handlers created, they may not behave as expected.
14

The direct translation is:

flights.forEach (d, i) ->
  d.index = i
  d.date = parseDate(d.date)
  d.delay = +d.delay
  d.distance = +d.distance

or you can use an idiomatic version:

for d,i in flights
  d.index = i
  d.date = parseDate(d.date)
  d.delay = +d.delay
  d.distance = +d.distance

2 Comments

That seems to result in a for loop. A forEach has subtle (or perhaps not so subtle) differences.
I was speaking WRT the second version. +1 for the first, which is the proper equivalent. I don't remember if it was there when I commented.
5

forEach has the advantage of wrapping each iteration in a closure. so asynchronous calls can preserve the correct values. the coffeescript way of doing this (without actually using forEach) is

for d,i in flights
  do (d, i)->
    d.index = i
    d.date = parseDate(d.date)
    d.delay = +d.delay
    d.distance = +d.distance

this compiles to something very similar to the OP's sample:

_fn = function(d, i) {
  d.index = i;
  d.date = parseDate(d.date);
  d.delay = +d.delay;
  return d.distance = +d.distance;
};
for (i = _i = 0, _len = flights.length; _i < _len; i = ++_i) {
  d = flights[i];
  _fn(d, i);
}

Use this if you need < ie9 support (forEach supported in IE starting version 9)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.