Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including tuplerone with all npm packages installed. Try it out:

var tuplerone = require("tuplerone")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

tuplerone v2.1.2

A yet another tuple implementation

tuplerone

Travis Coveralls Dev Dependencies

logo

A tuple data structure implementation in JavaScript based on ES2015 WeakMap.


Tuples are finite ordered sequences of values, and languages commonly implement tuples to allow grouping heterogenous data types and to provide immutability. JavaScript arrays can already include any types, but the purpose of having tuples in JavaScript is to simplify equality testing for groups of values and to use groups of values as keys in maps (Map, WeakMap).

This library is:

  • tiny (a couple of kilobytes minified), with no dependencies,
  • well-typed using TypeScript,
  • fully covered by tests.

The tuple objects are:

  • frozen – tuple object properties cannot be added, removed or changed,
  • array-like – tuple members can be accessed by indexing, and there's a length property, but no Array prototype methods,
  • iterable – tuple members can be iterated over using for-of loops or spread syntax.

There exists a stage-1 proposal for adding a similar feature to tuples to the base language.

Installation

npm install --save tuplerone

Usage

import { tuple } from "tuplerone";

// Dummy objects
const a = Object("a");
const b = Object("b");
const c = Object("c");

// Simple equality testing using the identity operator
tuple(a, b, c) === tuple(a, b, c); // → true
tuple(a, b) === tuple(b, a); // → false

// Mapping a pair of values to a different value 
const map = new Map();
map.set(tuple(a, b), 123).get(tuple(a, b)); // → 123

// Nesting tuples
tuple(a, tuple(b, c)) === tuple(a, tuple(b, c)); // → true

// Using primitive values
tuple(1, "a", a); // → Tuple(3) [1, "a", Object("a")]

// Indexing
tuple(a, b)[1]; // → Object("b")

// Checking arity
tuple(a, b).length; // → 2

// Failing to mutate
tuple(a, b)[0] = c; // throws an error

Advantages

Tuples simplify deep equality testing and can replace functions like isEqual() in lodash or having to stringify data to JSON to make it comparable, which can be difficult due to recursive references. Tuples can be compared efficiently, in constant time with the === identity operator.

This library uses a tree of WeakMap (for objects) or Map (for primitives) maps. The average time complexity of the access operations of JavaScript maps is O(1), so the access speed isn't reduced with the number of tuples created.

Using WeakMap for objects ensures that tuples and their members can be garbage collected once they become unreachable. For example:

let o = {};
// Create a new tuple that weakly references the object
tuple(o);
// Makes the object unreachable and thus also the tuple garbage collectable
a = null;

The tuple function can be thought of as memoizing the arguments to produce the same tuple object on each call.

Types

The library is well-typed using TypeScript:

import { tuple, Tuple } from "tuplerone";

// Dummy object
const o = {};

tuple() instanceof Tuple; // → true
tuple() as Tuple0; // 0-tuple
tuple(o) as Tuple1<typeof o>; // 1-tuple
tuple(o, 1) as Tuple2<typeof o, number>; // 2-tuple
tuple(o) === tuple(a, 1) // TS compile error due to different arities

The tuples are currently typed up to 8-tuple (octuple).

In editors like VS Code, the type information is also available when the library is consumed as JavaScript.

Caveats

Due to WeakMap being limited to using objects as keys, there must be at least one member of a tuple with the object type, or the tuples would leak memory. Trying to create tuples with only primitive members will throw an error.

tuple(1, 2); // throws TypeError
tuple(1, 2, {}); // works

WeakMap is an ES2015 feature which is difficult to polyfill, so this library is best used in environments like node or browser extensions where legacy support may not be needed.

tuplerone tuples are not supported by the relation comparison operators like <, whereas in a language like Python the following (comparing tuples by arity) would evaluate to true: (1,) < (1, 2).

Array-likeness

Tuples subclass Array:

Array.isArray(tuple()); // → true

Yet tuples don't share the Array prototype methods, since tuples are frozen in the constructor and this breaks most of the Array methods, which rely on mutation.

The advantage of extending Array is ergonomic console representation.

License

MIT

Author

slikts dabas@untu.ms

Metadata

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free