iterablefu
v0.4.5
Published
Small, chainable, set of functions like range, map, reduce, filter, zip, for iterable objects.
Downloads
610
Maintainers
Readme
IterableFu
IterableFu
is a small (1.2kb minimized and gzipped) library of functions like range, map, reduce, filter, zip, for iterable objects.
IterableFu
has a chainable class to make it easy to chain iterable transforms. There is a chainable class factory
makeChainableIterable, so you easily can add methods, or reduce bundle size.
Features
- Chainable:
chainable([0, 1, 2]).map(x => 2*x).toArray()
. - Works with your generators (and iterables):
chainable(yourGenerator()).mapWith(yourTransformGenerator)
. - Customizable makeChainableIterable, to add methods or reduce bundle sizes.
- Functional API takes data last, so you can curry, pipe and compose with your functional library.
- Exports both CommonJS and ES modules - dual package.
If you want asynchronous iterables along with task pool, event queue, pub/sub, merge, chunk, throttle, and the like, checkout await-for-it.
Table of Contents
- Installation
- Getting Started
- API
- Examples
- Smaller Bundles
- Customization
- Alternatives
- Contributing
- Issues
- License
Installation
npm install --save iterablefu
Getting Started
If you want the chainable API, use this import.
import { chainable } from 'iterablefu'
import { chainable } from 'iterablefu'
const iterable = chainable([1, 2, 3, 4, 5, 6]) // <-- throw any synchronous iterable in here
.filter(x => x % 2 === 0) // filters out odd numbers
.map(x => 2 * x)
console.log(Array.from(iterable)) // prints [4, 8, 12]
The most used methods are probably: zip
, zipAll
, filter
, flatten
, map
, and reduce
.
The documentation has an example for each method:
- chainable- Is a factory that starts the chain and produces a
ChainableIterable
- ChainableIterable - For all the transforms and reducer methods
If you want the functional API, use this import.
import { generators, transforms, reducers } from 'iterablefu'
You may also specify the modules directly to reduce bundle sizes. See more in the Smaller Bundles section.
API
- Chainable API
- Chainable factory, factory functions that produce
ChainableIterable
instances - ChainableIterable, chainable iterable generators, transforms, and reducers
- Custom chainables, create custom chainable iterables
- Chainable factory, factory functions that produce
- Functional API
- Generators, generator functions to create iterable sequences
- Transforms, functions to convert an iterable into another iterable (e.g. map, filter)
- Reducers, functions to convert an iterable into a value
Examples
Basics
IterableFu
provides three basic categories of functions:
- Generators - create an iterable sequence
- Transforms - convert one iterable sequence into another
- Reducers - convert an iterable sequence into a value
Here's a quick example showing range
(a generator), map
(a transform), and reduce
(a reducer).
import { chainable } from 'iterablefu'
const answer =
chainable
.range(5) // generates 0, 1, 2, 3, 4
.map(x => 2 * x) // maps to 0, 2, 4, 6, 8
.reduce((a, x) => a + x, 0) // 0 + 2 + 4 + 6 + 8 = 20
console.log(answer) // prints 20
Some generators can convert Arrays or any other iterable into chainable iterables.
const d = chainable([1, 2, 3]) // makes a chainable version of [1, 2, 3]
const e = chainable.concatenate([0, 1, 2], [3, 4]) // becomes [0, 1, 2, 3, 4]
const f = chainable.zip([1, 2, 3], ['a', 'b', 'c']) // becomes [[1, 'a'], [2, 'b'], [3, 'c']]
There are several ways to convert back to Arrays.
const a = Array.from(chainable.range(5)) // a has the value [0, 1, 2, 3, 4, 5]
const b = [...chainable.range(3)] // b has the value [0, 1, 2]
const c = chainable.range(2, 5).toArray() // c has the value [2, 3, 4, 5, 6]
One Time Use
Except for one method, repeatIterable
, IterableFu
only supports one-time iteration. This is because
iterators cannot be reused once done.
An iterable class like Array, can be iterated more than once because it produces a new iterator for each iteration.
// IterableFu produces one-time use sequences
const a = chainable.range(5)
console.log([...a]) // print [0, 1, 2, 3, 4], iterator is now done
console.log([...a]) // prints [] because the iterator was done before the call
To reuse an IterableFu
chain, wrap it in a function so that a new Generator object is returned each time it is called.
const fn = () => chainable.range(5)
// Note the function calls below...
console.log([...fn()]) // prints [0, 1, 2, 3, 4]
console.log([...fn()]) // prints [0, 1, 2, 3, 4] because a new iterator was used
Iterablefu and Your Generators
To use a generator function that creates a sequence, use chainable as a function.
// A simple generator function
const fn = function * (length) {
for (let i = 0; i < length; i++) {
yield i
}
}
// be sure to call the generator, don't just pass the function
const a = chainable(fn(3))
console.log([...a]) // prints [0, 1, 2]
To use a generator that transforms a sequence, use mapWith
.
// An example generator that transforms another sequence.
const fn = function * (n, iterable) {
for (let x of iterable) {
yield n * x
}
}
const input = [0, 1, 2, 3, 4]
// mapWith only accepts generator functions that have one parameter: iterable.
// If your generator takes additional parameters beyond iterable, you need
// to wrap it with another function that takes only one parameter. Like this:
const wrapper = (iterable) => fn(3, iterable)
const a = chainable(input).mapWith(wrapper).toArray()
console.log(a) // prints [0, 3, 6, 9, 12]
Smaller Bundles
You can potentially reduce bundle size by importing the generators and function you want to use directly.
import { zip, zipAll } from 'iterablefu/src/generators.js'
import { filter, flatten, map } from 'iterablefu/src/transfroms.js'
import { reduce } from 'iterablefu/src/reducers.js'
If you want a reduced size chainable object, use makeChainableIterable with the
directly imported functions. Customization is covered more completely in the makeChainableIterable
docs.
// using the imports from above
import { makeChainableIterable } from 'iterablefu/src/makechainable.js'
const generators = { zip, zipAll }
const transforms = { filter, flatten, map }
const reducers = { reduce }
const chainable = makeChainableIterable(generators, transforms, reducers)
Customization
Customization is covered in the makeChainableIterable documentation.
Alternatives
There are lots of alternatives:
- wu - has many more methods than
IterableFu
. Does not use ES6 modules. - itiri - many functions that force conversion to array. Typescript.
- lazy.js - more methods, does not use generators
- linq.js - LINQ (a .NET library) for JavaScript
- GenSequence - similar to
IterableFu
. Typescript.
... and many more.
Contributing
Contributions are welcome. Please create a pull request.
I use pnpm instead of npm.
Automated browser tests use electron. Automated package tests build a *.tgz
package and run tweaked unit tests in a temporary directory. Use pnpm run build
to run everything in the right order.
Issues
This project uses Github issues.
License
MIT