coll.mjs provides extended versions of JS data classes such as Set
and Map
, with better and/or additional APIs.
Port and rework of https://github.com/mitranim/jol.
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/coll.mjs'
Links: source; test/example.
Same as new
#Bset
but syntactically shorter and a function.
Links: source; test/example.
Same as #Bset
.of
but syntactically shorter and a function. The following is equivalent:
c.bsetOf(10, 20, 30)
c.Bset.of(10, 20, 30)
new c.Bset([10, 20, 30])
new c.Bset().add(10).add(20).add(30)
Links: source; test/example.
Short for "better set". Variant of built-in Set
with additional common-sense behaviors:
- Supports JSON encoding, behaving like an array.
- Supports adding other collections at any time by calling
.mut
, not just in the constructor. - Has additional instantiation shortcuts such as static
.of
.
Links: source; test/example.
Same as new
#Bmap
but syntactically shorter and a function.
Links: source; test/example.
Same as #Bmap
.of
but syntactically shorter and a function. The following is equivalent:
c.bmapOf(10, 20, 30, 40)
c.Bmap.of(10, 20, 30, 40)
new c.Bmap([[10, 20], [30, 40]])
new c.Bmap().set(10, 20).set(30, 40)
Links: source; test/example.
Short for "better map". Variant of built-in Map
with additional common-sense behaviors:
- Supports plain_dicts:
- Can be instantiated from a dict.
- Can be patched by a dict by calling
.mut
. - Can be converted to a dict by calling
.toDict
. - Behaves like a dict in JSON.
- Supports JSON encoding. Only entries with string keys are sent to JSON, other entries are ignored.
- Adding entries from another collection can be done any time by calling
.mut
, not just in the constructor. - Has additional instantiation shortcuts such as static
.of
.
Links: source; test/example.
Variant of #Bmap
with support for key and value checks. Subclasses must override methods .reqKey
and .reqVal
. These methods are automatically called by .set
. Method .reqKey
must validate and return the given key, and method .reqVal
must validate and return the given value. Use type assertions provided by lang
.
import * as l from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/lang.mjs'
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/coll.mjs'
class StrNatMap extends c.TypedMap {
reqKey(key) {return l.reqStr(key)}
reqVal(val) {return l.reqNat(val)}
}
Links: source; test/example.
Short for "primary key optional". Takes an arbitrary value and returns its "primary key". This is used internally by #Coll
and #ClsColl
.
Currently this uses the following interface:
interface Pkable {pk(): any}
Example use:
class Person {
constructor({name}) {this.name = name}
pk() {return this.name}
}
console.log(c.pkOpt(new Person({name: `Kara`})))
// 'Kara'
Links: source; test/example.
Short for "primary key". Similar to #pkOpt
, but the input must produce a non-nil primary key, otherwise this panics. This is used internally by #Coll
and #ClsColl
.
c.pk({})
// Uncaught TypeError: unable to get primary key of {}
class Person {
constructor({name}) {this.name = name}
pk() {return this.name}
}
c.pk(new Person({name: `Mira`}))
// 'Mira'
Links: source; test/example.
Short for "collection". Ordered map where values are indexed on their "primary key" determined by the function #pk
which is also exported by this module. Unlike a normal JS map, this is considered a sequence of values, not a sequence of key-value pairs. Order is preserved, iterating the values is decently fast, and the index allows fast access by key without additional iteration.
class Person {
constructor({name}) {this.name = name}
pk() {return this.name}
}
const coll = new c.Coll()
.add(new Person({name: `Mira`}))
.add(new Person({name: `Kara`}))
console.log(coll)
/*
Coll {
"Mira" => Person { name: "Mira" },
"Kara" => Person { name: "Kara" },
}
*/
console.log([...coll])
/*
[
Person { name: "Mira" },
Person { name: "Kara" },
]
*/
Links: source; test/example.
Variant of #Coll
where values must belong to a specific class, determined by its getter cls
. The default element class is Object
. Override it when subclassing. Elements added with .add
are idempotently instantiated.
Also see #ClsVec
.
class Person {
constructor({name}) {this.name = name}
pk() {return this.name}
}
class Persons extends c.ClsColl {
get cls() {return Person}
}
const coll = new Persons()
.add({name: `Mira`})
.add({name: `Kara`})
console.log(coll)
/*
Persons {
"Mira" => Person { name: "Mira" },
"Kara" => Person { name: "Kara" },
}
*/
Links: source; test/example.
Short for "vector". Thin wrapper around a plain array. Features:
- Implements the iterable interface.
- Compatible with spread operator
...
. - Compatible with
for of
. - JSON-encodes like an array.
- Can wrap a pre-existing array.
Differences and advantages over Array
:
- Better constructor signature.
- Can be subclassed without trashing performance.
- At the time of writing, subclasses of
Array
suffer horrible deoptimization in V8. Vec
always wraps a true, avoiding this problem.
- At the time of writing, subclasses of
The overhead of the wrapper is insignificant.
import * as c from 'https://cdn.jsdelivr.net/npm/@mitranim/[email protected]/coll.mjs'
console.log(new c.Vec())
// Vec{$: []}
console.log(new c.Vec([10, 20, 30]))
// Vec{$: [10, 20, 30]}
console.log(c.Vec.of(10, 20, 30))
// Vec{$: [10, 20, 30]}
console.log(c.Vec.from(new Set([10, 20, 30])))
// Vec{$: [10, 20, 30]}
for (const val of c.Vec.of(10, 20, 30)) console.log(val)
// 10 20 30
Links: source; test/example.
Variant of #Vec
where values must belong to a specific class, determined by its getter cls
. The default element class is Object
. Override it when subclassing ClsVec
. Elements added with .add
are idempotently instantiated.
Also see #ClsColl
.
class Person {
constructor({name}) {this.name = name}
pk() {return this.name}
}
class Persons extends c.ClsVec {
get cls() {return Person}
}
const coll = new Persons()
.add({name: `Mira`})
.add({name: `Kara`})
console.log(coll)
/*
Persons {
"$": [
Person { name: "Mira" },
Person { name: "Kara" },
]
}
*/
The following APIs are exported but undocumented. Check coll.mjs.