Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over ES6 Set/Map in Coffeescript (with `of` operator)

How can one iterate over an ES6 Map or Set in Coffeescript?

In Javascript one would use e.g.

s = new Set()
s.add({a: 1})
for (x of s) {
  console.log(x);
}

However Coffeescript has its own of operator that gets converted to in, i.e.:

console.log(x) for x of s

becomes ... for (x in s) { ... }.

How can one access Javascript's of operator in Coffeescript?

One could write their own custom iterator by cycling over s.values().next(), but that'd be an abomination. :)

like image 975
Brian M. Hunt Avatar asked Nov 03 '14 17:11

Brian M. Hunt


3 Answers

There's currently no way to use the new Javascript ES6 of operator from coffeescript (as of 1.9.2). The best option for now is to use s.forEach (x) -> ... or m.forEach (value, key) -> as mentioned above.

For a set:

s = new Set
s.add {a: 1}

s.forEach (v) =>
  console.log v

For a map:

m = new Map
m.set {a: 1}, {b: 2}

m.forEach (v, k) =>
  console.log k, v

If you want to avoid creating new functions for whatever reason, you can use iterators directly from coffeescript. But its a little bit nasty. For sets:

i = s.values()
while(v = i.next(); !v.done)
  console.log v.value

For a map:

i = m.entries()
while(v = i.next(); !v.done)
  [key, value] = v.value
  console.log key, value

The parentheses on the while loop are necessary to make the while loop dependant on v.done.

They can be done on one line too - but it looks pretty bad:

i = s.values(); console.log v.value while(v = i.next(); !v.done)
like image 191
Joseph Avatar answered Sep 29 '22 17:09

Joseph


Coffeescript 2.0 — for …from

JavaScript’s for…of is now available as CoffeeScript’s for …from (we already had a for …of): for n from generatorFunction()

Coffeescript 1.0 — Backticks

One option is to use the backtick to embed raw Javascript i.e. http://coffeescript.org/#embedded.

`for (x of y) { }`
like image 29
Brian M. Hunt Avatar answered Sep 29 '22 17:09

Brian M. Hunt


You want to do something like this:

eat food for food in ['toast', 'cheese', 'wine']

(where eat is a function)

In your case, you would do:

console.log(x) for x in s

Ref: http://coffeescript.org/#loops

It's helpful to use the coffeescript REPL. You can open it by typing coffee in your console. Try the following code:

_ = require 'underscore' #substitute underscore for lodash, if you prefer
s = ["a", "b", "c"]
console.log(x) for x in s

Edit:

Unfortunately, the Set functionality from ES6 doesn't seem to have made it into Coffeescript yet. Consider using underscore the lodash methods _.unique() or _.union() to mimic the functionality you're looking for.

For the example above:

s = _.unique ["a", "a", "b", "b", "b", "c"]
console.log(x) for x in s
like image 21
Ashwin Balamohan Avatar answered Sep 29 '22 18:09

Ashwin Balamohan