--- --- wu.js — Higher order functions for ECMAScript 6 iterators

wu.js


wu.js is a JavaScript library providing higher order functions (such as map, filter, and reduce) for ECMAScript 6 iterators.


Getting Started

In Modern Browsers Supporting ES6

Download the ES6 version
{% highlight html %} {% endhighlight %}

In Legacy ES5 Browsers

Download the ES5 debug build (non-minified, source-maps)
{% highlight html %} {% endhighlight %}

or

Download the ES5 production build (minified)
{% highlight html %} {% endhighlight %}

Node and npm

{% highlight bash %} $ npm install wu {% endhighlight %}

and

{% highlight js %} var wu = require("wu"); {% endhighlight %}

Note that this is the compiled-to-ES5 version.

Basics

Iterators represent a stream of data. To get the next value in the stream, you call the iterator's next method. This enables both lazy and infinite sequences. Most of the time you don't need to call next yourself: when you use a for-of loop, you're using iterators behind the scenes.

Anything can create iterators — they just need to make an object with the proper next interface — but generator functions and the yield expression provide convenient syntactic sugar.

{% highlight js %} // Generate an infinite sequence of the fibonacci numbers. function* fibs() { let a = 0; let b = 1; while (true) { yield a; [a, b] = [b, a + b]; } } // Log each even fibonacci number that is less than ten. const isEven = n => n % 2 == 0; const lessThanTen = n => n < 10; for (let n of fibs()) { if (!lessThanTen(n)) { break; } if (isEven(n)) { console.log(n); } } {% endhighlight %}

wu.js provides the higher order functions you've come to love from working with arrays (such as map and filter) as well as ones that may be new to JavaScript developers (such as takeWhile). With wu.js, we can rewrite the above example like this:

{% highlight js %} wu(fibs()) .filter(isEven) .takeWhile(lessThanTen) .forEach(console.log.bind(console)); {% endhighlight %}

Learn more about the ES6 iterator protocol at MDN.

Examples

Binary trees

The following is a simple immutable sorted set implementation that doesn't do tree balancing for simplicity. It has an iterator method which yields items in sorted order.

{% highlight js %} const theEmptySet = null; function SortedSet(value, left=theEmptySet, right=theEmptySet) { this.value = value; this.left = left; this.right = right; } SortedSet.prototype[wu.iteratorSymbol] = function* () { if (this.left !== theEmptySet) { yield* this.left; } yield this.value; if (this.right !== theEmptySet) { yield* this.right; } }; const insert = (set, x) => { if (set === theEmptySet) { return new SortedSet(x); } const { value, left, right } = set; if (x < value) { return new SortedSet(value, insert(left, x), right); } else if (x > value) { return new SortedSet(value, left, insert(right, x)); } else { return set; } }; {% endhighlight %}

We can initialize a set of 100 random floats to work with:

{% highlight js %} let s = theEmptySet; let n = 100; while (n--) { s = insert(s, Math.random()); } {% endhighlight %}

To get the sum of all elements greater than .8 in the set:

{% highlight js %} wu(s).dropWhile(n => n <= .8).reduce((x, y) => x + y); {% endhighlight %}

To find the number of elements that are less than .25:

{% highlight js %} wu(s).takeWhile(n => n < .25).length(); {% endhighlight %}

To find the first element whose square is greater than .5:

{% highlight js %} wu(s).filter(n => n * n > .5).find(n => n > .5); {% endhighlight %}

API

{% for p in site.posts %}
{{ p.content }}
{% endfor %}
{% include contributing.html %}