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
<script src="path/to/wu.js" defer></script>

In Legacy ES5 Browsers

Download the ES5 debug build (non-minified, source-maps)
<script src="https://raw.githubusercontent.com/mozilla/source-map/master/dist/wu.debug.js" defer></script>

or

Download the ES5 production build (minified)
<script src="https://raw.githubusercontent.com/mozilla/source-map/master/dist/wu.min.js" defer></script>

Node and npm

$ npm install wu

and

var wu = require("wu");

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.

// 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);
  }
}

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:

wu(fibs())
  .filter(isEven)
  .takeWhile(lessThanTen)
  .forEach(console.log.bind(console));

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.

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;
  }
};

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

let s = theEmptySet;

let n = 100;
while (n--) {
  s = insert(s, Math.random());
}

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

wu(s).dropWhile(n => n <= .8).reduce((x, y) => x + y);

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

wu(s).takeWhile(n => n < .25).length();

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

wu(s).filter(n => n * n > .5).find(n => n > .5);

API


Contributing

Development happens on GitHub. Include test(s) and documentation updates in your pull requests.

File bugs and feature requests in the GitHub issue tracker. When filing bugs, include:

  • Whether the bug occurs in the normal ES6 version, the compiled ES5 version, or both and what environment (eg specific browser or node version).
  • A testcase and steps to reproduce the bug with the testcase.
  • The expected results of executing the above steps.
  • The actual results of executing the above steps.

Building

To compile wu.js and its tests to ES5 using the Babel compiler, run:

$ npm run build

This command regenerates:

  • dist/wu.js — The ES5 compatible version of wu.js.
  • dist/wu.debug.js — The ES5 compatible version of wu.js with an inline source map included.
  • dist/wu.min.js — The minified ES5 compartible version of wu.js.

Tests

Running the Test Suite
$ npm test
Creating New Tests

To add a new test, find or create the appropriate file in test/test-X.js. Mocha is the test runner. Chai's assert module is used for assertions.

Documentation

This documentation is created with the static site generator Jekyll. To set up jekyll, run:

$ gem install jekyll bundler
$ cd path/to/wu.js
$ bundle install

Once Jekyll is set up, to serve the docs locally and automatically recompile them on change, run:

$ npm run docs

The documentation will be served at http://0.0.0.0:4000.

The sources for this documentation live in index.html and markdown files in the _posts directory. Each wu method has its own markdown file in the _posts directory, and the table of contents for thewu methods is generated automatically. The CSS styles live in index.css.