npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

terable

v0.3.0

Published

Functional ES2015 iterable utilities

Downloads

4

Readme

Terable Build Status

Terable is a wonderful library for using ES2015 iterables.

The functions it provides are comparable to a subset of lodash, but:

  • They accept iterables as input, and return iterables back (where appropriate)
  • They're lazy where possible (extremely lazy in fact), and have a functional API similar to lodash/fp (no method chaining!)
  • They're optimized to reduce the number of iterators and avoid creating intermediary data structures when composed together
  • Flow types are built-in

While lodash is an incredible library for what it does, it's not inteded to support iterables directly (requiring you to convert them using spread syntax). [1] The limited support it has for lazy evaluation will also likely be cut from version 5. [1] [2]

As an alternative, you may also want to look into iterare if you prefer method chaining and TypeScript support (though the functionality doesn't overlap completely).

Setup

yarn add terable
import * as it from 'terable';
// In Node
const it = require('terable');

// You can also import only the functions you need
import map from 'terable/map';
// In Node (note it's the .default export)
const map = require('terable/map').default;

The published source is transpiled to support Node 6 and IE11. However, you'll need some polyfills in IE11 and other browsers which don't support the following features:

  • Symbol.iterator
  • Iterator support for arrays and strings
  • Set (only for difference, intersect, union, uniq, and uniqBy)
  • Map (only for countBy, groupBy, intersect, and keyBy)

Generators aren't used, so you don't need the regenerator runtime to use this library.

Flow types are included with the package as separate *.js.flow files which are picked up by Flow automatically.

API

All functions are curried.

Most return values are iterables which can't be reused (i.e. iterated more than once), though some functions return a Set or Map which can of course be reused.

For usage examples, have a look at the tests.

all : <T>(test: (T) => mixed) => (Iterable<T>) => boolean

any : <T>(test: (T) => mixed) => (Iterable<T>) => boolean

compact : <T>(Iterable<T>) => Iterable<$NonMaybeType<T>>

concat : <T>(Iterable <Iterable<T>>) => Iterable<T>

concatMap : <T, U>(func: (T) => Iterable<U>) => (Iterable<T>) => Iterable<U>

countBy : <T, K>(func: (T) => K) => (Iterable<T>) => Map<K, number>

difference : <T>(sets: Iterable<Iterable<T>>) => Set<T>

drop : (count: number) => <T>(Iterable<T>) => Iterable<T>

each : <T>(func: (T) => mixed) => (Iterable<T>) => void

filter : <T, U>(test: ((T | U)) => mixed) => (Iterable<(T | U)>) => Iterable<U>

find : <T>(func: (T) => mixed) => (Iterable<T>) => T

foldl : <T, U>(func: (U, T) => U) => (U) => (Iterable<T>) => U

groupBy : <T, K>(func: (T) => K) => (Iterable<T>) => Map<K, Array<T>>

head : <T>(Iterable<T>) => T

intersect : <T>(sets: Iterable<Iterable<T>>) => Set<T>

join : (sep: string) => (Iterable<string>) => string

keyBy : <T, K>(func: (T) => K) => (Iterable<T>) => Map<K, T>

map : <T, U>(func: (T) => U) => (Iterable<T>) => Iterable<U>

sort : <T>(Iterable<T>) => Iterable<T>

sortBy : <T, K>(func: (T) => K) => (Iterable<T>) => Iterable<T>

take : (count: number) => <T>(Iterable<T>) => Iterable<T>

toArray : <T>(Iterable<T>) => Array<T>

toObject : <K, T>(entries: Iterable<[K, T]>) => {[K]: T}

union : <T>(sets: Iterable<Iterable<T>>) => Set<T>

uniq : <T>(Iterable<T>) => Iterable<T>

uniqBy : <T, U>(func: (T) => U) => (Iterable<T>) => Iterable<T>

Benchmarks

You can take these with a grain of salt. I used the benchmarks specifically to measure the performance of large iterator chains. Terable is slower at iterare's own benchmarks, and it would be quite easy to construct micro-benchmarks where lodash is 100x faster.

The main takeaway from these is that Terable isn't half-bad.

michael@Michaels-MacBook-Pro-2 ~/c/terable> node --version
v10.12.0
michael@Michaels-MacBook-Pro-2 ~/c/terable> for f in (ls bench); node "bench/$f"; echo; end
terable (intersect) x 225,798 ops/sec ±0.46% (92 runs sampled)
lodash (intersect) x 478,862 ops/sec ±1.00% (90 runs sampled)
ramda (intersect) x 15,731 ops/sec ±0.68% (94 runs sampled)
Fastest is lodash (intersect)

terable (large reduce) x 26,124 ops/sec ±0.46% (93 runs sampled)
iterare (large reduce) x 20,079 ops/sec ±0.46% (92 runs sampled)
lodash/fp (large reduce) x 12,826 ops/sec ±0.86% (91 runs sampled)
ramda (large reduce) x 66,106 ops/sec ±0.84% (89 runs sampled)
Fastest is ramda (large reduce)

terable (complex chain) x 515,600 ops/sec ±0.48% (86 runs sampled)
iterare (complex chain) x 435,195 ops/sec ±0.65% (93 runs sampled)
lodash/fp (complex chain) x 638,640 ops/sec ±0.49% (94 runs sampled)
ramda (complex chain) x 149,667 ops/sec ±0.82% (91 runs sampled)
Fastest is lodash/fp (complex chain)

terable (simple map) x 2,958,367 ops/sec ±1.63% (92 runs sampled)
terable (simple map, inline function) x 2,511,654 ops/sec ±0.56% (92 runs sampled)
iterare (simple map) x 4,129,526 ops/sec ±1.31% (89 runs sampled)
lodash/fp (simple map) x 437,384 ops/sec ±0.37% (94 runs sampled)
ramda (simple map) x 1,968,403 ops/sec ±1.20% (90 runs sampled)
Fastest is iterare (simple map)

terable (sortBy) x 374,045 ops/sec ±2.26% (78 runs sampled)
lodash/fp (sortBy) x 305,761 ops/sec ±0.48% (94 runs sampled)
ramda (sortBy) x 434,463 ops/sec ±1.05% (90 runs sampled)
Fastest is ramda (sortBy)

terable (take before map) x 6,319,365 ops/sec ±2.87% (90 runs sampled)
terable (take after map) x 6,399,383 ops/sec ±1.01% (91 runs sampled)
iterare (take before map) x 7,890,394 ops/sec ±1.65% (85 runs sampled)
iterare (take after map) x 7,583,817 ops/sec ±1.25% (88 runs sampled)
lodash/fp (take before map) x 257,589 ops/sec ±1.44% (91 runs sampled)
lodash/fp (take after map) x 243,316 ops/sec ±0.72% (96 runs sampled)
ramda (take before map) x 828,582 ops/sec ±0.81% (94 runs sampled)
ramda (take after map) x 802,170 ops/sec ±1.01% (94 runs sampled)
Fastest is iterare (take before map)