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 🙏

© 2025 – Pkg Stats / Ryan Hefner

transducers

v0.0.3

Published

Clojure inspired transducers implementation in JS

Downloads

30

Readme

Transducers NPM version Build Status Gitter

=========

Browser support

Library provides composable algorithmic transformations that are independent from the context of their input and output sources and specify only the essence of the transformation. In other words transducers are not coupled with a data they are operating & there for can operate on built-in JS types like arrays, strings, numbers, iterators as well as they could on custom types like Immutable.js data structures, RxJS Observables, CSP Channels or whatever else you may decide to use them for.

Following resources provide an excelent introduction to Transducers idea that this this library imlements.

API

transducers

map(f)

Applies f onto each item of the input data structure.

const {map} = require("transducers")
const inc = map(x => x + 1)

inc([2, 3, 4]) // => [3, 4, 5]

filter(p)

Keeps only items from input on which p(item) returned logical true.

const {filter} = require("transducers")
const isEven = x => !(x % 2)

filter(isEven)([1, 2, 3, 4]) // => [2, 4]

remove(p)

Removes items from input on with p(item) returned logical true.

const {remove} = require("transducers")
const isEven = x => !(x % 2)

remove(isEven)([1, 2, 3, 4]) // => [1, 3]

drop(n)

Drops first n number of items from the input.

const {drop} = require("transducers")

drop(2)([1, 2, 3, 4]) // => [3, 4]

dropWhile(p)

Drops items from the input while p(item) is logical true. Note that once p(item) returns logical false p is no longer applied to items.

const {dropWhile} = require("transdures")

dropWhile(x => x < 5)([1, 3, 7, 4, 9]) // => [7, 4, 9]

dropRepeats

Drops duplicate items form the input (equality compared with ===).

const {dropRepeats} = require("transducers")

dropRepeats([1, 2, 2, 2, 3, 3, 4]) // => [1, 2, 3, 4]

take(n)

Takes first n number of items from the input.

const {take} = require("transducers")

take(3)([1, 2, 3, 4, 5]) // => [1, 2, 3]

takeWhile(p)

Takes items as long as p(item) returns logical true. Note than once p(item) returns logical false p is no longer applied to items.

const {takeWhile} = require("transducers")

takeWhile(x => x < 5)([1, 4, 6, 5, 3]) // => [1, 4]

partition(n)

Collects inputs into arrays of size n. In case there are not enough padding items, last partition will have less than n items.

const {partition} = require("transducers")

partition(3)([0, 1, 2, 3, 4, 5]) // => [[0, 1, 2], [3, 4, 5]]
partition(3)([0, 1, 2, 3]) // => [[0, 1, 2], [3]]

cat

Concatenates items of the input. Assumes that items are collections.

const {cat} = require("transducers")

cat([[1, 2, 3], [4], [5, 6]]) // => [1, 2, 3, 4, 5, 6]

composition

If map is passed a transducer produces composed transducer:

(filter(isEven))
(map(inc))
([1, 4, 9, 10]) // => [5, 11]

mapcat

In fact library does not expose mapcat as it's pretty much made obsolete by a composition API.

map(x => x.split("/"))(cat)(["path/to", "dir/file"]) // => ["path", "to", "dir", "file"]

Different implementation

There are other two known implementations of [Transducers][] in JS:

In fact this library initially started as an attempt to enhance API of transducers.js and of a general idea, which also lead it to it's own path.

The core difference from both of the libraries is in the way transducers are composed & applied to input. In that regard it actually has more in common with fab.js than transducers.

transducer application

In above mentioned libraries transducer application happens through other functions like into, reduce & transduce & expectation is that data type constructors can take transducer to create transduced version of it. In contrast this library does not provide into and considers both reduce and transduce to be to low level APIs. For most common cases you would want to transform a data structure of a type to different data structure of the same type. In this library transducer functions can just take that data structure as an argument and return transformed version:

const inc = x => x + 1
map(inc)([1, 2, 3]) // => [2, 3, 4]
map(char => char.toUpperCase())("hello") // => "HELLO"

transducers can be applied to primitives

In this library transdures can also apply to primitives values like numbers just as well as they can to collections:

map(inc)(5) // => 6

any transformation over nil types like null and undefined is no op and return input back:

map(inc)(null) // => null
map(_ => 5)(null) // => null

transducer composition

Transducers in all of the libraries (including this one) can be composed with as a plain function composition that you know or at least have seen in [underscore.js][http://underscorejs.org/#compose]. Idea is simple composing f() and g() functions produces f(g()).

reduce(_.compose(x => x + 1, x => x * 2), 0, 2) // => 5

Although in case of transducers there is a surprising twist related to the implementation illustrated in the example below:

reduce(_.compose(map(x => x + 1), map(x => x * 2), [], [2]) // => [6]

Unlike right to left execution as in ordinary function composition execution order in transducers is from left to right instead. In order to avoid confusion & dependency on additional composition constructs this library takes inspiration from an API pioneered by fab.js a while back:

(map(x => x + 1))
(map(x => x * 2))
([2, 3]) // => [6, 8]

Execution is from top to bottom & no extra functions are need to compose them.

P.S.: You still could use _.compose but in that case avoid using application like _compose(f, g)([1, 2, 3]) as that won't do what you expect, given that input will be passed to g and then result to f instead of passing it to f.g composition.

License

MIT License