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

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

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

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

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.

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:

// Log each even fibonacci number that is less than ten.

// Generate an infinite sequence of the fibonacci numbers.

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.

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.

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

asyncEach wu(iterable).asyncEach(fn, maxBlock=wu.MAX_BLOCK, timeout=wu.TIMEOUT) wu.asyncEach(fn, maxBlock, timeout, iterable) curryable Call fn(item) for each item in the (possibly infinite) iterable. Every maxBlock milliseconds, do a setTimeout for timeout milliseconds so that we don’t hog the thread to ourselves. This gives the browser a chance to paint, fire an event handler, or run another concurrent asyncEach ’s set of calls. asyncEach returns a Promise that is resolved when iteration has completed. Note: It is generally preferrable to use a Worker instead of asyncEach when possible, as this will give you better throughput and responsiveness. However, if you absolutely must do iteration over a very large number of items on the main thread, asyncEach will let you do it without getting a slow-script-dialog for the tab. wu . count (). asyncEach ( x => console . log ( x )); // console.log: 0 // console.log: 1 // console.log: 2 // console.log: 3 // ...

chain wu.chain(...iterables) Form a single iterator from consequtive iterables. Yields items from the first iterable until it is exhausted, then yields items from the second iterable until that one is exhausted, and so on until all elements from all iterables have been yielded. wu . chain ( "ab" , "cd" , "ef" ) // ("a", "b", "c", "d", "e", "f")

chunk wu(iterable).chunk(n=2) wu.chunk(n, iterable) curryable Accumulate items from the iterable into arrays of size n and yield each array. wu ( "abcdef" ). chunk ( 2 ); // (["a", "b"], ["c", "d"], ["e", "f"]) wu ( "abcdef" ). chunk ( 3 ); // (["a", "b", "c"], ["d", "e", "f"]) wu ( "abcdef" ). chunk ( 4 ); // (["a", "b", "c", "d"], ["e", "f"])

concatMap wu(iterable).concatMap(fn) wu.concatMap(fn, iterable) curryable Applies the given function to each item in the iterable and yields each item from the result. wu ([ 1 , 2 , 3 ]). concatMap ( x => [ x , x * x ]) // (1, 1, 2, 4, 3, 9)

count wu.count(start=0, step=1) Yield an infinite set of numbers starting with start and incrementing by step . wu . count () // (0, 1, 2, 3, 4, 5, 6, ...) wu . count ( 5 ) // (5, 6, 7, 8, 9, 10, ...) wu . count ( 0 , 5 ) // (0, 5, 10, 15, 20, 25, ...)

curryable wu.curryable(fn, expected=fn.length) Returns a new function that keeps currying until it receives expected arguments, at which point it evaluates fn with those arguments applied. Learn more about currying at Wikipedia. Most of the functions attached directly to wu (eg wu.filter(fn, iterable) , as opposed to wu(iterable).filter(fn) ) are curryable. You generally shouldn’t need to explicitly specify the number of arguments expected unless you’re using rest parameters or optional parameters (which don’t add increment the function’s length property). const add = wu . curryable (( a , b ) => a + b ); add ( 3 , 4 ); // 7 const add2 = add ( 2 ); add2 ( 10 ) // 12 add ()()()()()()()()(); // function const sum = wu . reduce ( add , 0 ); sum ([ 1 , 2 , 3 , 4 , 5 ]); // 15 const hasProp = wu . curryable (( prop , obj ) => prop in obj ); const withAlias = wu . filter ( hasProp ( "alias" )); const wantedDeadOrAlive = [ { name : "Sammy Jones" , alias : "Crime Time" }, { name : "Jessica Carter" , alias : "Sugar Killa" }, { name : "Nick Fitzgerald" } ]; withAlias ( wantedDeadOrAlive ); // ( { name: "Sammy Jones", alias: "Crime Time" }, // { name: "Jessica Carter", alias: "Sugar Killa" } )

cycle wu(iterable).cycle() wu.cycle(iterable) curryable Yield each item from the iterable and when the iterable is exhausted, start yielding its items all over again, and again, and again. wu . cycle ([ 1 , 2 , 3 ]) // (1, 2, 3, 1, 2, 3, 1, 2, 3, ...)

drop wu(iterable).drop(n) wu.drop(n, iterable) curryable Drop the first n items from the iterable. wu ([ 5 , 4 , 3 , 2 , 1 ]). drop ( 2 ); // (3, 2, 1)

dropWhile wu(iterable).dropWhile(fn=Boolean) wu.dropWhile(fn, iterable) curryable Drop items from the iterable while the predicate is truthy. wu ([ 2 , 4 , 6 , 5 , 8 , 10 ]). dropWhile ( x => x % 2 === 0 ) // (5, 8, 10)

entries wu.entries(object) Yield [key, value] pairs from the given object. Ordering of the pairs is undefined and cannot be relied upon. const obj = { foo : 1 , bar : 2 , baz : 3 }; wu . entries ( obj ); // (["foo", 1], ["bar", 2], ["baz", 3])

enumerate wu(iterable).enumerate() wu.enumerate(iterable) curryable For each item in the iterable, yield a pair [item, index] . wu . enumerate ([ "cats" , "dogs" , "rats" , "hogs" ]); // (["cats", 0], ["dogs", 1], ["rats", 2], ["hogs", 3])

every wu(iterable).every(fn=Boolean) wu.every(fn, iterable) curryable Return true if fn(item) is truthy for every item in the iterable, otherwise return false . wu ([ true , 36 , "chambers" ]). every (); // true wu ([ true , false , true ]). every (); // false const allLessThan100 = wu . every ( x => x < 100 ); allLessThan100 ([ 1 , 2 , 3 , 4 , 5 ]); // true

filter wu(iterable).filter(fn=Boolean) wu.filter(fn, iterable) curryable Yield only the items from the iterable for which fn(item) is truthy. wu ([ false , true , false , true ]). filter () // (true, true) wu ([ 1 , 2 , 3 , 4 ]). filter ( x => x % 2 === 0 ) // (2, 4)

find wu(iterable).find(fn) wu.find(fn, iterable) curryable Return the first item from the iterable for which fn(item) is truthy. If no item is found, undefined is returned. const myTeam = [ { name : "Robert Fitzgerald Diggs" , alias : "RZA" }, { name : "Gary Grice" , alias : "GZA" }, { name : "Clifford Smith" , alias : "Method Man" }, { name : "Corey Woods" , alias : "Raekwon" }, { name : "Dennis Coles" , alias : "Ghostface Killah" }, { name : "Jason Hunter" , alias : "Inspectah Deck" }, { name : "Lamont Jody Hawkins" , alias : "U-God" }, { name : "Elgin Turner" , alias : "Masta Killah" }, { name : "Russell Tyrone Jones" , alias : "ODB" } ]; wu ( myTeam ). find (({ name }) => name . contains ( "Fitzgerald" )); // { name: "Robert Fitzgerald Diggs", alias: "RZA" }

flatten wu(iterable).flatten(shallow=false) wu.flatten(shallow, iterable) curryable Flatten the given iterable. If shallow is truthy, only flatten by one level. wu ([ "I" , [ "like" , [ "LISP" ]]]). flatten () // ("I", "like", "LISP") wu . flatten ( true , [ 1 , [ 2 ], [ 3 , [[ 4 ]]]]) // (1, 2, 3, [[4]]),

forEach wu(iterable).forEach(fn) wu.forEach(fn, iterable) curryable Call fn(item) for each item in the iterable. Note that this can cause slow script dialogs or even permanently block the main thread if used with large or infite iterators. In such cases, either use this method inside a Worker (preferrable) or use wu.asyncEach . wu . forEach ( x => console . log ( "x is " + x ), [ 1 , 2 , 3 ]); // console.log: "x is 1" // console.log: "x is 2" // console.log: "x is 3"

has wu(iterable).has(thing) wu.has(thing, iterable) curryable Returns true if thing is in the iterable (using === comparison), otherwise returns false . wu ([ "uno" , "dos" , "tres" ]). has ( 1 ); // false wu . count (). has ( 5 ); // true

invoke wu(iterable).invoke(methodName, ...args) wu.invoke(methodName, ...args, iterable) curryable For each item in the iterable, yield item[methodName](...args) . wu ([ 0 , 1 , 2 , 3 , 4 ]). invoke ( "toString" , 2 ); // ("0", "1", "10", "11", "100") function Animal ( type , noise ) { this . type = type ; this . noise = noise ; } Animal . prototype . makeNoise = function () { return this . type " says '" + this . noise + "'" ; } const animals = [ new Animal ( "cat" , "meow" ), new Animal ( "dog" , "woof" ), new Animal ( "rat" , "squeek" ), new Animal ( "hog" , "oink" ) ]; wu ( animals ). invoke ( "makeNoise" ); // ("cat says 'meow'", // "dog says 'woof'", // "rat says 'squeek'", // "hog says 'oink'")

keys wu.keys(object) Yield the property name of each enumerable property on the object. const obj = { uno : 1 , dos : 2 , tres : 3 }; wu . keys ( obj ); // ("uno", "dos", "tres")

map wu(iterable).map(fn) wu.map(fn, iterable) curryable Applies the given function to each item in the iterable and yields the result. wu ([ 1 , 2 , 3 ]). map ( x => x * x ); // (1, 4, 9)

nth wu(iterable).nth(n) wu.nth(n, iterable) curryable Return the nth item from the iterable. If n is out of bounds, undefined is returned. wu ([ 0 , 1 , 2 , 3 , 4 ]). nth ( 3 ); // 3

pluck wu(iterable).pluck(propertyName) wu.pluck(propertyName, iterable) curryable For each item in the iterable, yield item[propertyName] . const myTeam = [ { name : "Robert Fitzgerald Diggs" , alias : "RZA" }, { name : "Gary Grice" , alias : "GZA" }, { name : "Clifford Smith" , alias : "Method Man" }, { name : "Corey Woods" , alias : "Raekwon" }, { name : "Dennis Coles" , alias : "Ghostface Killah" }, { name : "Jason Hunter" , alias : "Inspectah Deck" }, { name : "Lamont Jody Hawkins" , alias : "U-God" }, { name : "Elgin Turner" , alias : "Masta Killah" }, { name : "Russell Tyrone Jones" , alias : "ODB" } ]; wu ( myTeam ). pluck ( "alias" ); // ("RZA", "GZA", "Method Man", ...)

reduce wu(iterable).reduce(fn[, initial]) wu.reduce(fn, initial, iterable) curryable Reduce the iterable from left to right with the binary function fn . If initial is supplied, start with that value, otherwise use the first value in the iterable. const plus = ( x , y ) => x + y ; wu ([ 1 , 2 , 3 , 4 , 5 ]). reduce ( plus ); // 15 wu . reduce ( plus , 100 , [ 1 , 2 , 3 , 4 , 5 ]); // 115

reductions wu(iterable).reductions(fn[, initial]) wu.reductions(fn, initial, iterable) curryable Similar to wu.reduce but yields each intermediate reduction as the iterable is reduced. const multiply = ( x , y ) => x * y ; wu . count ( 1 ). reductions ( multiply ); // (1, 2, 6, 24, 120, ...)

reject wu(iterable).reject(fn=Boolean) wu.reject(fn, iterable) curryable For each item in the iterable, yield the item if !fn(item) is truthy. wu ([ false , true , false , true ]). reject () // (false, false) wu ([ 1 , 2 , 3 , 4 ]). reject ( x => x % 2 === 0 ) // (1, 3)

repeat wu.repeat(thing, n=Inifinity) Create an iterable that yields thing n times. wu . repeat ( 42 ) // (42, 42, 42, 42, 42, ...) wu . repeat ( "hello" , 2 ) // ("hello", "hello")

slice wu(iterable).slice(start=0, stop=Infinity) wu.slice(start, stop, iterable) curryable Like Array.prototype.slice , but for any iterable. wu.slice(start, end, iterable) is equivalent to wu(iterable).drop(start).take(end - start) . wu . count ( 10 ). slice ( 1 , 4 ); // (11, 12, 13)

some wu(iterable).some(fn=Boolean) wu.some(fn, iterable) curryable Return true if fn(item) is truthy for any of the items in the iterable, otherwise return false . wu ([ false , false , true , false ]). some (); // true wu ([ 1 , 2 , 3 , 4 , 5 ]). some ( n => n > 10 ); // false

spreadMap wu(iterable).spreadMap(fn) wu.spreadMap(fn, iterable) curryable For each item in the iterable, yield fn(...item) . const pairs = [ [ 2 , 1 ], [ 2 , 2 ], [ 2 , 3 ], [ 2 , 4 ] ]; wu ( pairs ). spreadMap ( Math . pow ); // (2, 4, 8, 16)

take wu(iterable).take(n) wu.take(n, iterable) curryable Yield the first n items from the iterable. wu . count (). take ( 5 ); // (0, 1, 2, 3, 4)

takeWhile wu(iterable).takeWhile(fn=Boolean) wu.takeWhile(fn, iterable) curryable Yield items from the iterable while fn(item) is truthy. wu ([ 2 , 4 , 6 , 5 , 8 ]). takeWhile ( n => n % 2 === 0 ); // (2, 4, 6) wu ([ "foo" , "bar" , null , "baz" ]). takeWhile (); // ("foo", "bar")

tap wu(iterable).tap(fn=console.log.bind(console)) wu.tap(fn, iterable) curryable For each item in the iterable, call fn(item) and then yield item regardless of the function’s returned value. This is useful for debugging chained methods. const pairs = [ [ 2 , 1 ], [ 2 , 2 ], [ 2 , 3 ], [ 2 , 4 ] ]; const log = msg => console . log . bind ( console , msg ); const iter = wu ( pairs ) . tap ( log ( "initial: " )) . spreadMap ( Math . pow ) . tap ( log ( "after spreadMap: " )) . map ( n => n + 1 ) . tap ( log ( "after + 1: " )) . reject ( n => n < 7 ) . tap ( log ( "after reject: " )); iter . next (). value ; // console.log: initial: [2, 1] // console.log: after spreadMap: 2 // console.log: after + 1: 3 // console.log: initial: [2, 2] // console.log: after spreadMap: 4 // console.log: after + 1: 5 // console.log: initial: [2, 3] // console.log: after spreadMap: 8 // console.log: after + 1: 9 // console.log: after reject: 9 // 9 iter . next (). value ; // console.log: initial: [2, 4] // console.log: after spreadMap: 16 // console.log: after + 1: 17 // console.log: after reject: 17 // 17

tee wu(iterable).tee(n=2) wu.tee(n, iterable) curryable Split the given iterable into n duplicate iterators. Warning: once you’ve split an iterator with tee , you shouldn’t use the original iterator again, or else the new iterators will get out of sync! function * fibs () { let a = 0 ; let b = 1 ; while ( true ) { yield a ; [ a , b ] = [ b , a + b ]; } } const [ fibs1 , fibs2 ] = wu ( fibs ()) . tap ( console . log . bind ( console , "Calculated a fib:" )) . tee (); fibs1 . next (). value ; // console.log: Calculated a fib: 0 // 0 fibs1 . next (). value ; // console.log: Calculated a fib: 1 // 1 fibs1 . next (). value ; // console.log: Calculated a fib: 1 // 1 fibs1 . next (). value ; // console.log: Calculated a fib: 2 // 2 fibs1 . next (). value ; // console.log: Calculated a fib: 3 // 3 fibs1 . next (). value ; // console.log: Calculated a fib: 5 // 5 // Note that each value is only calculated once! fibs2 . next (). value ; // 0 fibs2 . next (). value ; // 1 fibs2 . next (). value ; // 1

toArray wu(iterable).toArray() Converts an iterable to an Array. wu . count (). take ( 5 ). toArray (); // [0, 1, 2, 3, 4]

unique wu(iterable).unique() wu.unique(iterable) curryable For each item in the iterable, yield only the first occurence of the item. Note that all yielded items from the iterable are kept in a Set , so memory overhead may become significant while iterating over large collections. wu ([ 1 , 2 , 1 , 1 , 3 , 2 , 3 ]). unique (); // (1, 2, 3)

unzip wu(iterable).unzip(n=2) wu.unzip(n, iterable) curryable Given an iterable whose items are of the form [a, b, c, ...] , return an array of iterators of the form [as, bs, cs, ...] . const pairs = [ [ "one" , 1 ], [ "two" , 2 ], [ "three" , 3 ] ]; const [ i1 , i2 ] = wu ( pairs ). unzip (); i1 ; ( "one" , "two" , "three" ) i2 ; ( 1 , 2 , 3 )

values wu.values(object) Yield the property value of each enumerable property on the object. const obj = { uno : 1 , dos : 2 , tres : 3 }; wu . values ( obj ); // (1, 2, 3)

zip wu.zip(...iterables) Given n iterables, yield the next item from each iterable as an array until the shortest iterable is exhausted. wu . zip ( "hello" , [ 3 , 2 , 1 ]); // (["h", 3], ["e", 2], ["l", 1])

zipLongest wu.zipLongest(...iterables) The same as wu.zip , but keeps going until the longest iterable is exhausted. When shorter iterables have been exhausted, undefined is used in place of their next items. wu . zipLongest ( "hello" , [ 3 , 2 , 1 ]); // (["h", 3], ["e", 2], ["l", 1], ["l", undefined], ["o", undefined])