stdtraits

Highly gen­eric traits/​in­ter­faces.

Laws

These ap­ply to all traits in this mod­ule.

  • Ar­rays, Strings and any list-like data struc­tures are treated as map­pings from in­dex -> value
  • Ar­ray sparse­ness is ig­nored on read; any list-like con­tainer has a spe­cific in­dex if size(my­Con­tainer) => key; get­ting an un­set value yields un­defined
  • Sets are treated as map­pings from a key to it­self
Source:

Interfaces

Assign
Deepclone
Delete
Equals
Get
Has
Immutable
Pairs
Replace
Setdefault
Shallowclone
Size

Methods

(inner) assertEquals(a, b, msg)

Source:
See:

As­sert that eq(ac­tual, ex­pec­ted)

const { throws: as­sertThrows } = re­quire('assert');
const { as­ser­tEquals } = re­quire('fer­rum');

as­ser­tEquals([{foo: 42}], [{foo: 42}]); // OK!
as­sertThrows(() => as­ser­tEquals([1,2,3], [1,2]));

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
b B
msg String | undefined

The er­ror mes­sage to print

Throws:
AssertionError

(inner) assertUneq(a, b, msg)

Source:
See:

As­sert that !eq(ac­tual, ex­pec­ted)

const { throws: as­sertThrows } = re­quire('assert');
const { as­ser­tUneq } = re­quire('fer­rum');

as­ser­tUneq(1, 2);
as­sertThrows(() => as­ser­tUneq([{foo: 42}], [{foo: 42}])); // As­ser­tion­Error!

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
b B
msg String | undefined

The er­ror mes­sage to print

Throws:

AssertionError

(inner) assign(cont, key, value)

Source:

Set a value in a con­tainer. Al­ways re­turns the given value.

const { as­sign, each, as­ser­tEquals } = re­quire('fer­rum');

const o = {};
const m = new Map();
const a = [];

// Nor­mal as­sign­ment
as­sign(o, 'foo', 42);
as­ser­tEquals(o, { foo: 42 });

// As­sign­ment us­ing cur­ry­ing
each([o, m, a], as­sign(2, 'bar'));
as­ser­tEquals(o, { foo: 42, 2: 'bar' });
as­ser­tEquals(m, new Map([[ 2, 'bar' ]]));
as­ser­tEquals(a, [un­defined, un­defined, 'bar']);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
cont *

The con­tainer

key *

The key

value *

The value to set

(inner) deepclone(a) → {A}

Source:
See:

Re­curs­ively clone an ob­ject

const { not­Stric­tEqual: as­sertIs­Not } = re­quire('assert');
const { deep­clone, as­ser­tEquals, as­ser­tUneq } = re­quire('fer­rum');

const a = {foo: []};
const b = deep­clone(a);

// After clon­ing, the top level ele­ment is equal to the ori­ginal,
// but it is a clone.
as­sertIs­Not(a, b);
as­ser­tEquals(a, b);

// The chil­dren are also cloned, mutat­ing them will not propag­ate
// to the ori­gina
b.foo.push(42);
as­sertIs­Not(a.foo, b.foo);
as­ser­tUneq(a.foo, b.foo);
as­ser­tEquals(a.foo, []);
as­ser­tEquals(b.foo, [42])

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
Returns:
Type
A

(inner) del(x, k)

Source:

De­lete an entry with the given key from a con­tainer

const { del, each, as­ser­tEquals } = re­quire('fer­rum');

const o = { foo: 42, bar: '13' };
const m = new Map([[ 'foo', true ]]);

// Nor­mal as­sign­ment
del(o, 'bar');
as­ser­tEquals(o, { foo: 42 });

// As­sign­ment us­ing cur­ry­ing
each([o, m], del('foo'));
as­ser­tEquals(o, {});
as­ser­tEquals(m, new Map());

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
x *

The con­tainer to de­lete from

k *

The key to de­lete

(inner) empty(what) → {Boolean}

Source:
See:

De­term­ine if a con­tainer is empty. Uses size(x) === 0a

const as­sert = re­quire('assert');
const { empty, re­ject, as­sertSequenceEquals } = re­quire('fer­rum');

as­sert(empty([]));
as­sert(empty({}));
as­sert(!empty("asd"));

// This is also par­tic­u­larly use­ful as a pre­dic­ate for se­quence
// func­tions like fil­ter, re­ject, con­tains, find, etc.
// Eg. the fol­low­ing code will re­move any empty con­tain­ers from a se­quence
// re­gard­less of type
const re­jec­tEmpty = re­ject(empty);

as­sertSequenceEquals(
  re­jec­tEmpty([{foo: 23}, "", [], new Set(), "42"]),
  [{foo: 23}, "42"]);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
what T
Returns:
Type
Boolean

(inner) eq(a, b) → {Boolean}

Source:
See:

De­term­ine whether two val­ues are equal us­ing the Equals trait.

const as­sert = re­quire('assert');
const { eq, as­sertSequenceEquals, re­ject } = re­quire('fer­rum');

// Should give the same res­ults as `===` for prim­it­ive val­ues
as­sert(eq(true, true));
as­sert(eq(null, null));
as­sert(eq(un­defined, un­defined));
as­sert(eq("asd", "asd"));
as­sert(eq(Sym­bol.iter­ator, Sym­bol.iter­ator));
as­sert(!eq("", 0));
as­sert(!eq(1, 2));

// Can also com­pare more com­plex struc­tures
as­sert(eq([{foo: 42}], [{foo: 42}]));
as­sert(!eq([{foo: 42}], [{bar: 11}]));

// This is also par­tic­u­larly use­ful as a pre­dic­ate for se­quence
// func­tions like fil­ter, re­ject, con­tains, find, etc.
// Eg. the fol­low­ing code will re­move any ob­jects equal to {foo: 23}
const inp = [{foo: 42}, {foo: 23}, {foo: 23, bar: 1}];
as­sertSequenceEquals(
  re­ject(inp, eq({foo: 23})),
  [{foo: 42}, {foo: 23, bar: 1}]);

This func­tion is a bit more power­ful than than the Equals trait it­self: First of all it searches for a Equals im­ple­ment­a­tion for both ar­gu­ments and it falls back to === if none is found. For this reason us­ing eq() is usu­ally pre­ferred over us­ing the Equals trait dir­ectly.

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
b B
Returns:
Type
Boolean

(inner) get(x, k) → {*}

Source:

Given a key, get a value from a con­tainer.

Nor­mally you would use the ob­ject[value] op­er­ator for this or Map::get. The ad­vant­age of us­ing this func­tion is that it works for any con­tainer (that im­ple­ments the Trait), so it helps you write more gen­eric func­tions.

const { stric­tEqual: as­sertIs } = re­quire('assert');
const { get, as­sertSequenceEquals, map } = re­quire('fer­rum');

as­sertIs(get({foo: 42}, 'foo'), 42);

// Get is par­tic­u­larly use­ful for more com­plex use cases; in this
// ex­ample for in­stance we ex­tract the key `1` from a vari­ety of con­tain­ers;
const inp = [
  ['foo', 'bar'],
  new Map([[1, 42]]),
  new Set([1]),
  {1: 'bang'},
];

as­sertSequenceEquals(
  map(inp, get(1)),
  ['bar', 42, 1, 'bang']);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
x *

The con­tainer to get the key of. Must im­ple­ment the Get trait.

k *

The key to re­trieve the value for

Returns:

The value

Type
*

(inner) has(x, k)

Source:

Test if a con­tainer in­cludes an entry with the given key

const as­sert = re­quire('assert');
const { has, fil­ter, as­sertSequenceEquals } = re­quire('fer­rum');

as­sert(has({foo: 42}, 'foo'));
as­sert(!has({foo: 42}, 'bar'));

// Get is par­tic­u­larly use­ful with fil­ter/​re­ject/​find/...
// This ex­ample will re­turn all con­tain­ers that have the 'value' key
const dat = [{ value: 13 }, { ford: 42 }];
as­sertSequenceEquals(
  fil­ter(dat, has('value')),
  [{ value: 13 }]);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
x *

The con­tainer

k k

The key to check

(inner) isImmutable(v) → {Boolean}

Source:
See:

Test whether a given value is im­mut­able.

const as­sert = re­quire('assert');
const { isIm­mut­able } = re­quire('fer­rum');

as­sert(isIm­mut­able(42));
as­sert(isIm­mut­able('asd'));
as­sert(isIm­mut­able(Sym­bol()));
as­sert(isIm­mut­able(null));
as­sert(isIm­mut­able(un­defined));
as­sert(isIm­mut­able(/​asd/));
​as­sert(isIm­mut­able(() => {}));

as­sert(!isIm­mut­able({}));
as­sert(!isIm­mut­able([]));
as­sert(!isIm­mut­able(new Map()));
as­sert(!isIm­mut­able(new Set()));
Parameters:
Name Type Description
v T
Returns:
Type
Boolean

(generator, inner) keys(what)

Source:
See:

Get an iter­ator over the keys of a con­tainer. Uses pairs(c).

const {keys, as­sertSequenceEquals} = re­quire('fer­rum');

as­sertSequenceEquals(keys(['a', 'b']),      [0, 1]);
as­sertSequenceEquals(keys(new Set([1, 2])), [1, 2]);
as­sertSequenceEquals(keys({foo: 42}),       ['foo']);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
what T
Yields:
The keys of the container

(inner) pairs(what) → {Array}

Source:
See:

Get an iter­ator over any con­tainer. Al­ways re­turns pairs [key, value], this dis­tin­guishes pairs() from iter()/nor­mal it­er­a­tion.

Note that usu­ally you should use iter() over pairs un­less you really know that for­cing a con­tainer into key/​value rep­res­ent­a­tion is needed (e.g. Ar­ray with in­dices) since pairs() will only work on a very se­lect num­ber of con­tain­ers, while iter() will work on any iter­at­ors and will ac­tu­ally sup­port lists of key value pairs.

const { pairs, as­sertSequenceEquals } = re­quire('fer­rum');

as­sertSequenceEquals(pairs("as"),            [[0, "a"], [1, "s"]]);
as­sertSequenceEquals(pairs({foo: 42}),       [['foo', 42]]);
as­sertSequenceEquals(pairs(['a', 'b']),      [[0, 'a'], [1, 'b']]);
as­sertSequenceEquals(pairs(new Set([1, 2])), [[1, 1], [2, 2]]);
as­sertSequenceEquals(pairs(
  new Map([["foo", "bar"], ["baz", "bang"]])),
  [["foo", "bar"], ["baz", "bang"]]);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
what T
Yields:
Key/Value Pairs
Type
Array

(inner) replace(x, k, v) → {*}

Source:

Swap out one value in a con­tainer for an­other.

const { re­place, map, as­ser­tEquals, as­sertSequenceEquals } = re­quire('fer­rum');

const o = { foo: 42 };
const m = new Map([[ 'bar', 'hel­lo' ]]);

// Nor­mal as­sign­ment
as­ser­tEquals(re­place(o, 'bar', 1), un­defined);
as­ser­tEquals(re­place(o, 'foo', 2), 42);
as­ser­tEquals(o, { foo: 2, bar: 1});

// As­sign­ment us­ing cur­ry­ing
as­sertSequenceEquals(
  map([o, m], re­place('bar', 'world')),
  [ 1, 'hel­lo' ]);
as­ser­tEquals(o, { foo: 2, bar: 'world' });
as­ser­tEquals(m, new Map([[ 'bar', 'world' ]]));

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
x *

The con­tainer to re­place a value in

k *

The key of the value to re­place

v *

The new value

Returns:

Whatever the value was be­fore the re­place.

Type
*

(inner) setdefault(x, k, v) → {*}

Source:

If the key is present in the con­tainer, re­turn the value as­so­ci­ated with the key. Oth­er­wise, as­sign the sup­plied de­fault value to the key and re­turn that value.

const { set­de­fault, map, as­ser­tEquals, as­sertSequenceEquals } = re­quire('fer­rum');

const o = { foo: 42 };
const m = new Map();

// Nor­mal as­sign­ment
as­ser­tEquals(set­de­fault(o, 'bar', 1), 1);
as­ser­tEquals(set­de­fault(o, 'foo', 2), 42);
as­ser­tEquals(o, { foo: 42, bar: 1});

// As­sign­ment us­ing cur­ry­ing
as­sertSequenceEquals(
  map([o, m], set­de­fault('foo', 3)),
  [ 42, 3 ]);
as­ser­tEquals(o, { foo: 42, bar: 1 });
as­ser­tEquals(m, new Map([[ 'foo', 3 ]]));

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
x *

The con­tainer

k *

The key to search for

v *

The de­fault value

Returns:

Whatever the con­tainer now has as­so­ci­ated with k.

Type
*

(inner) shallowclone(a) → {A}

Source:
See:

Shal­lowly clone an ob­ject

const { stric­tEqual: as­sertIs, not­Stric­tEqual: as­sertIs­Not } = re­quire('assert');
const { shal­low­clone, as­ser­tEquals, as­ser­tUneq } = re­quire('fer­rum');

const a = {foo: []};
const b = shal­low­clone(a);

// The res­ult­ing value must be equal to the in­put, but be a clone
as­sertIs­Not(a, b);
as­ser­tEquals(a, b);

// All chil­dren are still the same, so mutat­ing them propag­ates
// to the ori­ginal ele­ment.
b.foo.push(42);
as­sertIs(a.foo, b.foo);
as­ser­tEquals(a.foo, b.foo);
as­ser­tEquals(a.foo, [42]);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
Returns:
Type
A

(inner) size(what) → {Number}

Source:
See:

De­term­ine the size of a con­tainer. Uses the Size trait.

const { stric­tEqual: as­sertIs } = re­quire('assert');
const { size } = re­quire('fer­rum');

as­sertIs(size({foo: 42}), 1);
as­sertIs(size([1,2,3]),   3);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
what T
Returns:
Type
Number

(inner) typeIsImmutable(t) → {Boolean}

Source:
See:

Test whether in­stance of a given type is im­mut­able.

const as­sert = re­quire('assert');
const { typeIs­Im­mut­able } = re­quire('fer­rum');

as­sert(typeIs­Im­mut­able(String));
as­sert(typeIs­Im­mut­able(Num­ber));
as­sert(typeIs­Im­mut­able(Sym­bol));
as­sert(typeIs­Im­mut­able(un­defined));
as­sert(typeIs­Im­mut­able(null));
as­sert(typeIs­Im­mut­able(Reg­Exp));
as­sert(typeIs­Im­mut­able(Func­tion));

as­sert(!typeIs­Im­mut­able(Ob­ject));
as­sert(!typeIs­Im­mut­able(Ar­ray));
as­sert(!typeIs­Im­mut­able(Map));
as­sert(!typeIs­Im­mut­able(Set));
Parameters:
Name Type Description
t Type
Returns:
Type
Boolean

(inner) uneq(a, b) → {Boolean}

Source:
See:

Equi­val­ent to !eq(a, b)

const as­sert = re­quire('assert');
const { uneq } = re­quire('fer­rum');

as­sert(uneq(4, 5));
as­sert(!uneq({}, {}));

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
a A
b B
Returns:
Type
Boolean

(generator, inner) values(what)

Source:
See:

Get an iter­ator over the val­ues of a con­tainer.

Uses the Pairs trait.

const { val­ues, as­sertSequenceEquals } = re­quire('fer­rum');

as­sertSequenceEquals(val­ues(['a', 'b']),      ['a', 'b']);
as­sertSequenceEquals(val­ues(new Set([1, 2])), [1, 2]);
as­sertSequenceEquals(val­ues({foo: 42}),       [42]);

Ver­sion his­tory

  • 1.2.0 Sup­port for ob­jects with Sym­bol keys.
Parameters:
Name Type Description
what T
Yields:
The values of the container