Revealing CoffeeScript’s Best Kept Secret

Iterables, Async Iterables, Generators and Async Generators

Wilfred Springer
Published in
3 min readJan 21, 2019

--

Call me a dinosaur, but I still consider many features of CoffeeScript superior to TypeScript, ES6 or any other language that compiles to JavaScript. There’s just one thing that started to annoy me. I couldn’t figure out how to deal with Iterables, and async generators. Somehow, Google didn’t help me in finding out how to do it, and the documentation on https://coffeescript.org/ is, well, “sparse”.

Iterators

Let’s start with Iterators. Iterators are easy. All you need is something with a next() method that returns an object holding the value and an indication if we should proceed . In the example below, range is a function accepting an upper and lower bound, producing an iterator. Neither JavaScript nor CoffeeScript have anything baked into the language for iterating over the elements, so you need something that looks a little clumsy to iterate through all elements.

Iterables

Iterables are where the fun starts. Iterables are simply objects with a method that produces an iterator. The name of that method is defined by the standard. Interestingly, it’s name is not a String but a Symbol instead. Which makes it challenging, if you missed out on a feature of the latest version of CoffeeScript that is mentioned only once, and briefly mentioned in the change log.

This would be the naive approach. In this particular case, I’m using CoffeeScript’s string interpolation solution for defining the key based on a constant defined somewhere else, in this case in Symbol.iterator.

Doesn’t work! The key must not be a String, but a Symbol instead.

That doesn’t work, and if you realize that the key is expected to be a Symbol , that makes perfect sense. Luckily, the latest versions of CoffeeScript actually allow you to use the same syntax for defining keys dynamically as you can find in ES6:

With that, we can now use the for-comprehension over iterables as a more convenient way to list all the values in the range.

Generators

This is the easy bit. CoffeeScript has support for writing generators, omitting some of the boilerplate JavaScript code:

Async Generators

Unfortunately, in many of the circumstances, your data will be the result of something getting retrieved asynchronously. Let’s change our range function to return Promises of values instead:

Note the await in for await i from range(0, 10).

Async Iterable

There may be cases in which you cannot use an async generator. In that case, it’s worthwhile knowing that you can also implement an async Iterable:

--

--

Wilfred Springer

Double bass playing father of three, hacker and soul searcher