IterizerJs makes it easier to write code that makes extensive use of ES6 iterables. Banish the arcane C-style for
loop, and write cleaner, more expressive and concise code instead.
Why you might want to use IterizerJs:
- More Concise Code: ES6 Iterables/Generators + ES5 Array Methods + IterizerJs = More Expressive & More Concise code.
-
Better Functional Re-use: Generator Funcitons combined with the IterizerJs's
limit()
method lead to higher code re-use at the functional level. -
Project Euler Hardened: IterizerJs was discovered by attempting to solve the first ten problems in Project Euler using ES6 iterables/generators and the ES5
Array
methods.
IterizerJs is not a polyfill, but a library to help you get the most out of ES6 generators. See the GitHub page for details on where you can use it, and how to install it.
More Concise Code
For example, here's the solution for problem 6 in Project Euler:
function sumOfSquares(n) {
return range(n).map(function(n) {return n * n}).sum();
}
function squaresOfSums(n) {
return Math.pow(range(n).sum(), 2);
}
console.log(squaresOfSums(10) - sumOfSquares(10));
Better Functional Re-use
To solve problems 3 & 7 from Project Euler in ES5 we might end up creating primes(numPrimes)
, primes(maxPrime)
& nthPrime(n)
methods, whereas with IterizerJs we can create a single primes()
generator function, and achieve the variations using:
primes().limit(numPrimes)
primes().limit(lessThanOrEqualTo(maxPrime))
primes().nthPrime(n)
increasing re-use at the functional level.
With IterizerJs
When we later encounter problem 10 from Project Euler ('Find the sum of all the primes below two million'), our intuitions are confirmed when we can solve the problem with this single line of code:
primes().limit(lessThan(2000000)).sum();
With ES6
Alternatively, using only what's available in ES6, you would instead have to write something like this:
function* lessThan(num, items) {
for(var n of items) {
if(n < num) {
yield n;
}
else {
return;
}
}
}
Array.from(lessThan(2000000, primes())).sum();
which merely begins to duplicate the functionality provided by IterizerJs anyway.
Globally Installing IterizerJs
Although IterizerJs can be required, parts of it are designed to be installed globally, and the benefits of IterizerJs diminish when this can't be done. There are two flavours of global installation:
- Global functions (e.g.
range()
, rather than having to typeit.range()
) - Additional methods on built-in objects (Methods are added to
Object
andString
)
Accordingly, two types of installation are typical:
-
Installation By App: we recommend
it.install()
is invoked since apps are free to affect global state. -
Installation By Library: we recommend
it.installMethods()
is invoked since libraries must take care to inter-operate with all other libraries.
Libraries that are unwilling to install any globals can still use IterizerJs, but will find it of limited value in comparison.
All examples from this point on will assume that the install()
method has been called, and that all IterizerJs methods are available globally.
Counted Loops
Thanks to ES6, you will never need to write an arcane C-style for
loop again. Instead, you can write code like this:
for(var n of range(10)) {
// do something with the numbers from 1 to 10
}
Unlike C, Java & JavaScript, etc, which are zero-based, the provided range()
method is one-based, since zero based counting normally only makes sense if you are doing pointer arithmetic, or if you are using old-style for
loops to index zero-based arrays. Since for...of
and for...in
allow arrays to be iterated without maintaining an index, and since real-world problems are normally one based, the range()
functions start from one unless instructed otherwise.
To iterate the numbers 0 to 9, we could instead write:
for(var n of range(0, 9)) {
// do something...
}
we can count down from 10 to 1 by inverting the arguments:
for(var n of range(10, 1)) {
// do something...
}
or we could iterate only even numbers from 2 to 10 by providing a step
argument, for example:
for(var n of range(2, 10, 2)) {
// do something with the numbers 2, 4, 6, 8, 10
}
ES5 Array Methods
IterizerJs provides implementations of the ES5 Array methods, map()
, filter()
, every()
, some()
& reduce()
, that operate on iterables, and which themselves return an iterable. These can be chained together to produce concise yet descriptive code, such as:
range(-5, 5).filter(isGreaterThan(0)).map(times(10));
Limiting what an iterable object or generator function returns.
Whereas with normal functions, it is often necesarry to create multiple variants of a function depending on what you need it to return, with ES6 generator functions it is often easier to produce functions that return all possible results, and then limit how long they run for externally. To help with this, a limit()
method is provided that can be used as follows:
// display the first 5 prime numbers
primes().limit(5);
Or to instead display the 5th to 10th prime numbers we could write:
primes().limit(5, 10);
Alternatively, to display all primes whose value is less than 100, we can write:
primes().limit(isLessThan(100));
To show exactly the 100th prime we can write:
primes().limit(100,100);
or better yet, use the nthItem()
convenience method:
primes().nthItem(100);
Similarly, to get the first item we can use the first()
method as follows:
primes().first();
Filters
IterizerJs comes with a number of helpful filter functions that can be used with the filter()
and limit()
methods. These include the numeric filters:
isLessThan(num)
isLessThanOrEqualTo(num)
isGreaterThan(num)
isGreaterThanOrEqualTo(num)
and the string based filters:
equals(str)
beginsWith(str)
endsWith(str)
contains(str)
matches(regExp)
All of the filters can be negated by preceding them with not
, for example:
programmers().filter(not.equals('Dominic Chambers'));
String Iteration
IterizerJs provides a chars()
method for iterating strings which can be used as follows:
// produces the string 'a,b,c'
'abc'.chars().join();
Other helpful methods
A number of other helpful methods like join()
, toArray()
, sum()
& product()
are also provided. At any time, the definitive list of available methods can be found by scanning the source code.
Alternatives
Some alternatives to IterizerJs:
- The
Array.from()
method in ES6 can be used to convert an iterable to a array, allowing indirect use of the ES5 array methods with iterables. However, prematurely converting iterables to arrays removes many of the advantages they confer. That being said, this may be a good compromise for people that want fewer dependencies.
If you know of any other alternatives to IterizerJs please let me know so I can link them here.