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

@sullux/fp-light-compose

v0.0.1

Published

A lightweight functional library for functional composition and object composition.

Downloads

4

Readme

fp-light-compose

npm i @sullux/fp-light-compose source test

Compose has different meanings for objects as for functions. Functional composition is the inverse of piping. Object composition is the recursive combination of the fields of multiple input objects into a single output object.

compose

compose(...args: Function[] | Object[]): Function | Object

If the first argument is a function, returns the functional composition of the arguments; otherwise, returns the object composition of the arguments.

composeObjects

composeObjects(...objects: Object[]) : Object

Performs a deep composition of the given objects and returns an immutably-composed object. Note: this is different from the shallow composition offered by the spread operator or the Object.Assign() function. The following test illustrates the difference.

const { deepStrictEqual } = require('assert')
const { composeObjects } = require('@sullux/fp-light-compose')

const first = {
  outer: {
    isFirst: true,
    inner: {
      foo: 42
    }
  }
}

const second = {
  outer: {
    isFirst: false,
    inner: {
      bar: 'baz'
    }
  }
}

const composed = composeObjects(first, second)
const spread = { ...first, ...second }
const assign = Object.assign({}, first, second)

deepStrictEqual(composed, {
  outer: {
    isFirst: false,
    inner: {
      foo: 42, // here because of deep composition
      bar: 'baz'
    }
  }
})

deepStrictEqual(spread, {
  outer: {
    isFirst: false,
    inner: {
      bar: 'baz' // `foo` is missing because of shallow composition
    }
  }
})

deepStrictEqual(spread, assign) // assign and spread are both shallow

Some other notes about object composition:

  • The composed object and all composed nested objects are immutable.
  • Composition uses last-in-wins logic unless both child values are composable.
  • Child values are composable if both values are of type object and neither value is a date or an iterable.

composeFunctions

Composition is a core principle of functional programming. When the result of one function is the argument to another function, the classical notation is as follows:

third(second(first(42)))

The result of first(42) is passed to second, and the result of that is passed to third. The composition of these functions looks like the following test.

const { strictEqual } = require('assert')
const { composeFunctions } = require('@sullux/fp-light-compose')

const first = x => x / 2
const second = x => x / 7
const third = x => x + 39

const allThree = composeFunctions(third, second, first)

strictEqual(
  third(second(first(42))), // manually composed
  allThree(42)              // pre-composed
)

strictEqual(allThree(42), 42)

The following example demonstrates how composeFunctions is the exact inverse of pipe.

const { strictEqual } = require('assert')
const { composeFunctions } = require('@sullux/fp-light-compose')
const { pipe } = require('@sullux/fp-light-pipe')

const first = x => x / 2
const second = x => x / 7
const third = x => x + 39

strictEqual(
  compose(third, second, first)(42),
  pipe(first, second, third)(42)
)

Functional composition is async-aware. If a composed function returns a thenable (such as a Promise), the each subsequent function will be invoked on the resolved value and the composition will return a Promise to the final result. This is demonstrated in the following example.

const { strictEqual } = require('assert')
const { compose } = require('@sullux/fp-light-compose')

const doubleOfSquare = compose(
  value => value + value,
  value => Promise.resolve(value * value)
)

doubleOfSquare(3)
  .then(result => strictEqual(result, 18))