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

fp-booleans

v0.5.2

Published

Utilities to apply boolean logic (not, and, or) to functions and higher-order functions. Tiny, tested and composable

Downloads

270

Readme

fp-booleans

A collection of utility functions to apply boolean logic on functions (including higher-order).

Written (and can be used) in a functional programming style.

fp-booleans functions are:

  1. Small
  2. Pure
  3. Zero-dependencies
  4. Tree-shakeable
  5. Fully tested by design

Functions

  1. not()
  2. and()
  3. or()

Why

Being able to combine or negate booleans, predicate functions and higher-order predicate functions means lots of 💪 power. With a flexible yet simple API and TS annotations this can be easy too.

Examples

not()

Unary function: accepts boolean, predicate, higher-order predicate.

On predicates

We can use not() on a predicate function to "reverse" it and get a function with the same signature but opposite logic

const notGreaterThan100 = not(greaterThan100);
const fail = notGreaterThan100(score);
// same as
const fail = not(greaterThan100)(score)
On a higher order functions

The best part is we can also use it on a higher-order function that returns a predicate:

const greaterThan = (comparison: number) => (arg: number) => arg > comparison;

// we now have several options:

// we could just reverse the boolean value
const fail = not(greaterThan(100)(score))
// or the predicate (which is a partially-applied HoF)
const fail = not(greaterThan(100))(score);
// or reverse the higher-order function itself
const fail = not(greaterThan)(100)(score);

[!TIP] Being able to move parenthesis around is not for the sake of 🤹 juggling code. This flexibility allows to have the complexity (and unit tests) in one single function, partially apply it as much as needed and then applying boolean operations on the specialized function without the need of writing several similar functions (and testing them, as the partial application is declarative in nature).Imagine if instead than a simple score > 100 logic in our examples we had a complex function… Negating it or combining it could require writing several slightly different versions of the logic (that should all be unit tested). With not() we can avoid this duplication.

On boolean values (or expressions)

This is the simplest use case: Imagine we want to pass or fail a level in a game based on the score being greater than 100:

const greaterThan100 = (n: number) => n > 100;
const pass = greaterThan100(score);
const fail = !pass;

The ! only works on the boolean value (or equivalent expression), not on the function reference.

In this case we could use not() to just reverse the boolean value or expression. (nothing fancy here, just equivalent to !)

const fail = not(pass);

but not() can also be used as mapper:

const flippedValues = [true, false].map(not); // [false, true]
const flippedValues = [true, false].map(not as (value: boolean) => boolean); // [false, true]

and()

N-ary function.

Combining functions is a foundation of functional programming.

Imagine again some code where we are granting a special bonus score based on some logic:

const isBonusScore = score => score % 2 === 0 && score > 0 && score <= 100;

This code, while still being simple, is hard to read, to test and maintain. This kind of code tends to be infused with business logic and be rewritten with mild differences in several places. Combining simpler functions would help almost not writing code and ease readability using a declarative syntax.

The first step would be to isolate the logic into simpler functions:

const isEven = n => n % 2 === 0;
const isGreaterThan = compare => n => n > compare;
const isBetween = (min, max) => isGreaterThan(min) && not(isGreaterThan(max));

[!NOTE] This is a one-time job (or no job at all if you already have them or use some external package) and once tested these functions are going to be bullet-proof.

With these utils in place, we could create one function that combines expressions (booleans) with the && operator, but it would require to have a function signature, invoke all functions, and passing the same parameter and would look like:

const isBonusScore = score => isEven(score) && isBetween(0, 100)(score);

Instead, we could just and() (combine the function references) and go point-free.

const isBonusScore = and(isEven, isBetween(0, 100));
isBonusScore(50); // true

See how combining functions references is more compact than combining expressions in a function?

or()

What just described about the and() function applies to or(). E.g.:

const isValid = or(isNegative, isGreaterThan(100));

All together

fp-booleans functions can be all combined to unleash infinite 🚀 power:

not(is(5));
not(is)(5);
and(greaterThanOrEqual(MIN_PRICE), not(isRound));
or(is('admin'), and(startsWith('user_'), isLowerCase));

Used in filters

Can be used in filters:

array.filter(not(is(5)));
array.filter(and(
    greaterThanOrEqual(MIN_PRICE),
    not(isRound))
);
array.filter(or(
        is('admin'),
        and(
            startsWith('user_'),
            isLowerCase)
    )
);

[!TIP] fp-booleans is used at the core of fp-filters, a curated list of filter functions. Check it, and you may never have to write another filter function 🚀!

Additional Exports

Two more utils functions are exported:

  1. isPredicate
  2. isHigherOrderPredicate

they can check if a function is a predicate (returns boolean) or is a higher-order predicate (a function that when invoked returns a predicate).

Examples

isPredicate(someFunction);
isHigherOrderPredicate(someFunction);

Getting started

Installation

fp-booleans runs on Node.js and is available as a NPM package.

npm install --save fp-booleans

or

yarn add fp-booleans

License

MIT

Copyright (c) 2023-present, Pierluigi Pesenti