HiveBrain v1.2.0
Get Started
← Back to all entries
snippetjavascriptTip

Numeric range generator in JavaScript

Submitted by: @import:30-seconds-of-code··
0
Viewed 0 times
javascriptgeneratorrangenumeric

Problem

JavaScript ES6 generators allow you to define functions that can be exited and later re-entered, while retaining their context (variable bindings). They are defined using function (function keyword followed by an asterisk) and use yield expressions to return their result. But how can one use them to create a range generator that produces a sequence of numbers?
As the control flow of generators is tricky to grasp at first, let's start with the simplest possible range implementation. We'll only account for an end value, starting at 0 and incrementing by 1. What we need to do to accomplish this is to use a for loop and yield the value of i at each iteration.
Consuming the output of a generator can be done step-by-step, as needed, or all at once. Depending on our needs we have a few available options.
We can, for example, use the generator object to call Generator.prototype.next() until it returns { value: undefined, done: true } to iterate over the values the generator produces.
As shown in the previous example, we can also use for...of to iterate over the generator's output. This is due to the fact that generators are iterable objects, implementing Symbol.iterator under the hood.

Solution

const range = function* (end) {
  for (let i = 0; i < end; i++) yield i;
};

for (let i of range(5)) console.log(i);
// Logs: 0, 1, 2, 3, 4


Consuming the output of a generator can be done step-by-step, as needed, or all at once. Depending on our needs we have a few available options.
We can, for example, use the generator object to call Generator.prototype.next() until it returns { value: undefined, done: true } to iterate over the values the generator produces.
As shown in the previous example, we can also use for...of to iterate over the generator's output. This is due to the fact that generators are iterable objects, implementing Symbol.iterator under the hood.
Finally, we can also use the spread operator (...) to consume the generator's output all at once. This is especially useful when you want to convert the generator's output into an array.
Having implemented the most basic version of a range generator, we can now extend it to accept start and step parameters. This will allow us to define a range that starts at a specific value and increments by a specific step.
In order to match the behavior of Python's range() function, we need to account for the following scenarios:

Code Snippets

const range = function* (end) {
  for (let i = 0; i < end; i++) yield i;
};

for (let i of range(5)) console.log(i);
// Logs: 0, 1, 2, 3, 4
const gen5 = range(5);
let x = gen5.next();

while (!x.done) {
  console.log(x.value);
  x = gen5.next();
}
// Logs: 0, 1, 2, 3, 4
for (let i of range(5)) console.log(i);
// Logs: 0, 1, 2, 3, 4

Context

From 30-seconds-of-code: range-generator

Revisions (0)

No revisions yet.