No Description

Sven Slootweg 158c9223b8 Initial commit 4 months ago
.gitignore 158c9223b8 Initial commit 4 months ago
README.md 158c9223b8 Initial commit 4 months ago
index.js 158c9223b8 Initial commit 4 months ago
package.json 158c9223b8 Initial commit 4 months ago

README.md

dataprog

A few simple utility functions to support a better way of writing Javascript.

Proper documentation coming soon, this is still under development.

The concept (draft)

Programming is ultimately centered around transforming and deriving data. Purely functional programming languages are centered around that premise, but people often find them impractical to use.

The interesting thing about JS is that it borrows pretty heavily from functional languages, while not being particularly restrictive. This makes it an interesting choice to write your code primarily around data transformations, without a high barrier to entry; however, JS is still missing a few features that would really make it work well.

This library aims to provide some of those features, in the form of utility functions. Ultimately it's up to you to write your code well - more about how to do that will be added to this documentation later - and this library simply serves to provide standardized implementations of a few handy patterns.

API

expression(func)

Turn anything into an expression, by wrapping it within an immediately-evaluated function. Especially useful to build the equivalent of match expressions (which JS doesn't have yet) using a regular if/else chain.

const { expression } = require("dataprog");

function speakNumber(number) {
	let name = expression(() => {
		if (number === 1) {
			return "one";
		} else if (number === 2) {
			return "two";
		} else if (number === 3) {
			return "three";
		} else {
			return "unknown";
		}
	});

	console.log(`That number is ${name}`);
}

merge(object, [object], [object], ...)

Merge any amount of objects into a single new one. This works a bit like Object.assign, with a few differences:

  1. None of the provided objects are mutated.
  2. If you pass in only null/undefined values, this function will return null. Object.assign would have thrown an error.

syncPipe(value, functions)

A userland implementation of pipelines. Handles synchronous operations only, see ppipe for a version that supports Promises. Also sometimes known as 'waterfall'.

Specify a value and a series of functions that transform that value into a new value, eventually returning the final value from the syncPipe call.

  • value: The initial value.
  • functions: An array of transformation functions, or a single transformation function (though that is somewhat pointless).
const dateFns = require("date-fns");
const { syncPipe } = require("dataprog");

function msUntilNextMinute() {
	return syncPipe(getTime(), [
		(_) => dateFns.addMinutes(_, 1),
		(_) => dateFns.setSeconds(_, 0),
		(_) => dateFns.differenceInMilliseconds(_, getTime())
	]);
}

The _ is just a variable name here, you could call it anything you want - but giving it a consistent name will help with readability, as all of the arrow function bodies will be visually aligned.

asyncPipe(value, functions)

Like syncPipe, but each function in functions may return either a synchronous value or a Promise, and the call to ppipe will always return a Promise that resolves to the final value.

  • value: The initial value.
  • functions: An array of transformation functions, or a single transformation function.
const { asyncPipe } = require("dataprog");

// ...

function getContentType(item) {
	return asyncPipe(item, [
		(_) => _.getHeaders(),
		(_) => _["content-type"]
	]);
}

For asyncPipe, which handles asynchronous operations, it can actually be useful to use the single-function syntax to quickly pick a property out of an asynchronously-obtained object:

const { asyncPipe } = require("dataprog");

// ...

function getContentType(item) {
	return ppipe(item.getHeaders(), (headers) => headers["content-type"]);
}

objectFind(object, predicate)

Analogous to Array#find. Finds the first entry that matches the predicate, and returns its [ key, value ], or undefined if there were no matches.

The predicate is called value-first, since usually the values are what you care about.

const { objectFind } = require("dataprog");

let object = {
	a: 1,
	b: 2,
	c: 3,
	d: 4,
	e: 5
};

let match = objectFind(object, (value, key) => value % 2 === 0);
console.log(match); // [ b, 2 ]

objectIncludes(object, predicate)

Like objectFind, but returns true or false depending on whether the object contained an entry that matches the predicate. Analogous to Array#some.