Skip to content

Commit

Permalink
refactor(associative): rename EquivMap/Set => ArrayMap/Set, export in…
Browse files Browse the repository at this point in the history
…terfaces
  • Loading branch information
postspectacular committed Apr 13, 2018
1 parent a769856 commit 8756027
Show file tree
Hide file tree
Showing 12 changed files with 119 additions and 116 deletions.
48 changes: 48 additions & 0 deletions packages/associative/src/api.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,51 @@
import { Predicate2, Comparator } from "@thi.ng/api/api";

export type Pair<K, V> = [K, V];

export const SEMAPHORE = Symbol("SEMAPHORE");

export interface ArrayMapOpts<K> {
equiv: Predicate2<K>;
}

export interface ArraySetOpts<T> {
equiv: Predicate2<T>;
}

/**
* SortedMapOpts implementation config settings.
*/
export interface SortedMapOpts<K> {
/**
* Key equivalence predicate. MUST return truthy result if given
* keys are considered equal.
*
* Default: `@thi.ng/api/equiv`
*/
equiv: Predicate2<K>;
/**
* Key comparison function. Must follow standard comparator contract
* and return:
* - negative if `a < b`
* - positive if `a > b`
* - `0` if `a == b`
*
* Note: The `SortedMap` implementation only uses `<` comparisons.
*
* Default: `@thi.ng/api/compare`
*/
compare: Comparator<K>;
/**
* Initial capacity before resizing (doubling) occurs.
* This value will be rounded up to next pow2.
* Default: 16
*/
capacity: number;
/**
* Probability for a value to exist in any express lane.
* Default: `1 / Math.E`
*/
probability: number;
}

export type SortedSetOpts<T> = SortedMapOpts<T>;
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
import { ICopy, IEmpty, IEquiv, IObjectOf, Predicate2 } from "@thi.ng/api/api";
import { equiv } from "@thi.ng/api/equiv";

import { SEMAPHORE, Pair } from "./api";
import { EquivSet } from "./equiv-set";
import { ArrayMapOpts, Pair, SEMAPHORE } from "./api";
import { ArraySet } from "./array-set";

interface EqMapProps<K, V> {
keys: EquivSet<K>;
interface MapProps<K, V> {
keys: ArraySet<K>;
map: Map<K, V>;
}

export interface EqMapOpts<K> {
equiv: Predicate2<K>;
}

const __private = new WeakMap<EquivMap<any, any>, EqMapProps<any, any>>();
const __private = new WeakMap<ArrayMap<any, any>, MapProps<any, any>>();

export class EquivMap<K, V> extends Map<K, V> implements
export class ArrayMap<K, V> extends Map<K, V> implements
Iterable<Pair<K, V>>,
ICopy<EquivMap<K, V>>,
IEmpty<EquivMap<K, V>>,
ICopy<ArrayMap<K, V>>,
IEmpty<ArrayMap<K, V>>,
IEquiv {

static fromObject<T>(obj: IObjectOf<T>): EquivMap<PropertyKey, T> {
const m = new EquivMap<PropertyKey, T>();
static fromObject<T>(obj: IObjectOf<T>): ArrayMap<PropertyKey, T> {
const m = new ArrayMap<PropertyKey, T>();
for (let k in obj) {
if (obj.hasOwnProperty(k)) {
m.set(k, obj[k]);
Expand All @@ -34,7 +30,7 @@ export class EquivMap<K, V> extends Map<K, V> implements
constructor(pairs?: Iterable<Pair<K, V>>, eq: Predicate2<K> = equiv) {
super();
__private.set(this, {
keys: new EquivSet<K>(null, eq),
keys: new ArraySet<K>(null, eq),
map: new Map<K, V>(),
});
if (pairs) {
Expand All @@ -47,7 +43,7 @@ export class EquivMap<K, V> extends Map<K, V> implements
}

get [Symbol.species]() {
return EquivMap;
return ArrayMap;
}

get size() {
Expand All @@ -61,12 +57,12 @@ export class EquivMap<K, V> extends Map<K, V> implements
}

empty() {
return new EquivMap<K, V>(null, __private.get(this).keys.getOpts().equiv);
return new ArrayMap<K, V>(null, __private.get(this).keys.getOpts().equiv);
}

copy() {
const $this = __private.get(this);
const m = new EquivMap<K, V>();
const m = new ArrayMap<K, V>();
__private.set(m, {
keys: $this.keys.copy(),
map: new Map<K, V>($this.map)
Expand Down Expand Up @@ -160,7 +156,7 @@ export class EquivMap<K, V> extends Map<K, V> implements
return __private.get(this).map.values();
}

getOpts(): EqMapOpts<K> {
getOpts(): ArrayMapOpts<K> {
return __private.get(this).keys.getOpts();
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import { ICopy, IEmpty, IEquiv, Predicate2 } from "@thi.ng/api/api";
import { equiv } from "@thi.ng/api/equiv";
import { DCons } from "@thi.ng/dcons";
import { SEMAPHORE, Pair } from "./api";

interface EqSetProps<T> {
vals: DCons<T>;
equiv: Predicate2<T>;
}
import { ArraySetOpts, Pair, SEMAPHORE } from "./api";

export interface EqSetOpts<T> {
interface SetProps<T> {
vals: DCons<T>;
equiv: Predicate2<T>;
}

const __private = new WeakMap<EquivSet<any>, EqSetProps<any>>();
const __private = new WeakMap<ArraySet<any>, SetProps<any>>();

/**
* An alternative set implementation to the native ES6 Set type. Uses
Expand All @@ -23,10 +20,10 @@ const __private = new WeakMap<EquivSet<any>, EqSetProps<any>>();
* Additionally, the type also implements the `ICopy`, `IEmpty` and
* `IEquiv` interfaces itself.
*/
export class EquivSet<T> extends Set<T> implements
export class ArraySet<T> extends Set<T> implements
Iterable<T>,
ICopy<EquivSet<T>>,
IEmpty<EquivSet<T>>,
ICopy<ArraySet<T>>,
IEmpty<ArraySet<T>>,
IEquiv {

constructor(vals?: Iterable<T>, eq: Predicate2<T> = equiv) {
Expand All @@ -40,7 +37,7 @@ export class EquivSet<T> extends Set<T> implements
}

get [Symbol.species]() {
return EquivSet;
return ArraySet;
}

get size() {
Expand All @@ -49,13 +46,13 @@ export class EquivSet<T> extends Set<T> implements

copy() {
const $this = __private.get(this);
const s = new EquivSet<T>(null, $this.equiv);
const s = new ArraySet<T>(null, $this.equiv);
__private.get(s).vals = $this.vals.copy();
return s;
}

empty() {
return new EquivSet<T>(null, __private.get(this).equiv);
return new ArraySet<T>(null, __private.get(this).equiv);
}

clear() {
Expand Down Expand Up @@ -167,7 +164,7 @@ export class EquivSet<T> extends Set<T> implements
yield* this.keys();
}

getOpts(): EqSetOpts<T> {
getOpts(): ArraySetOpts<T> {
return { equiv: __private.get(this).equiv };
}
}
4 changes: 2 additions & 2 deletions packages/associative/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export * from "./equiv-map";
export * from "./equiv-set";
export * from "./array-map";
export * from "./array-set";
export * from "./sorted-map";
export * from "./sorted-set";

Expand Down
4 changes: 2 additions & 2 deletions packages/associative/src/indexed.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { EquivMap } from "./equiv-map";
import { ArrayMap } from "./array-map";
import { selectKeysObj } from "./select-keys";

/**
Expand All @@ -7,7 +7,7 @@ import { selectKeysObj } from "./select-keys";
* @param ks keys used for indexing
*/
export function indexed(records: Set<any>, ks: PropertyKey[]) {
const res = new EquivMap<any, Set<any>>();
const res = new ArrayMap<any, Set<any>>();
let m, ik, rv;
for (m of records) {
ik = selectKeysObj(m, ks);
Expand Down
6 changes: 3 additions & 3 deletions packages/associative/src/join.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { IObjectOf } from "@thi.ng/api/api";

import { EquivSet } from "./equiv-set";
import { ArraySet } from "./array-set";
import { intersection } from "./intersection";
import { indexed } from "./indexed";
import { invertObj } from "./invert";
Expand All @@ -24,7 +24,7 @@ export function join<A, B>(xrel: Set<A>, yrel: Set<B>) {
s = xrel;
}
const idx = indexed(r, ks);
const res = new EquivSet<any>();
const res = new ArraySet<any>();
for (let x of s) {
const found = idx.get(selectKeysObj(x, ks));
if (found) {
Expand Down Expand Up @@ -53,7 +53,7 @@ export function joinWith<A, B>(xrel: Set<A>, yrel: Set<B>, km: IObjectOf<Propert
}
const idx = indexed(r, objValues(k));
const ks = Object.keys(k);
const res = new EquivSet<any>();
const res = new ArraySet<any>();
for (let x of s) {
const found = idx.get(renameKeysObj(selectKeysObj(x, ks), k));
if (found) {
Expand Down
38 changes: 1 addition & 37 deletions packages/associative/src/sorted-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,48 +5,12 @@ import { illegalArgs } from "@thi.ng/api/error";
import { isArray } from "@thi.ng/checks/is-array";
import { map } from "@thi.ng/iterators/map";

import { Pair, SEMAPHORE } from "./api";
import { Pair, SEMAPHORE, SortedMapOpts } from "./api";

// stores private properties for all instances
// http://fitzgeraldnick.com/2014/01/13/hiding-implementation-details-with-e6-weakmaps.html
const __private = new WeakMap<SortedMap<any, any>, SortedMapProps>();

/**
* SortedMapOpts implementation config settings.
*/
export interface SortedMapOpts<K> {
/**
* Key equivalence predicate. MUST return truthy result if given
* keys are considered equal.
*
* Default: `@thi.ng/api/equiv`
*/
equiv: Predicate2<K>;
/**
* Key comparison function. Must follow standard comparator contract
* and return:
* - negative if `a < b`
* - positive if `a > b`
* - `0` if `a == b`
*
* Note: The `SortedMap` implementation only uses `<` comparisons.
*
* Default: `@thi.ng/api/compare`
*/
compare: Comparator<K>;
/**
* Initial capacity before resizing (doubling) occurs.
* This value will be rounded up to next pow2.
* Default: 16
*/
capacity: number;
/**
* Probability for a value to exist in any express lane.
* Default: `1 / Math.E`
*/
probability: number;
}

interface SortedMapProps {
head: any[];
tail: any[];
Expand Down
8 changes: 3 additions & 5 deletions packages/associative/src/sorted-set.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { ICopy, IEmpty, IEquiv, ICompare } from "@thi.ng/api/api";
import { map } from "@thi.ng/iterators/map";

import { Pair } from "./api";
import { SortedMap, SortedMapOpts } from "./sorted-map";
import { Pair, SortedSetOpts } from "./api";
import { SortedMap } from "./sorted-map";
import { compare } from "@thi.ng/api/compare";

export type SortedSetOpts<T> = SortedMapOpts<T>;

const __private = new WeakMap<SortedSet<any>, SortedMap<any, any>>();

/**
Expand Down Expand Up @@ -144,7 +142,7 @@ export class SortedSet<T> extends Set<T> implements
return __private.get(this).get(value, notFound);
}

getOpts() {
getOpts(): SortedSetOpts<T> {
return __private.get(this).getOpts();
}
}
16 changes: 8 additions & 8 deletions packages/associative/test/difference.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as assert from "assert";

import { EquivSet } from "../src/equiv-set";
import { ArraySet } from "../src/array-set";
import { difference } from "../src/difference";

describe("difference", () => {
Expand All @@ -11,10 +11,10 @@ describe("difference", () => {
assert.deepEqual(difference(a, b), new Set([1, 2]));
});

it("equiv (numbers)", () => {
const a = new EquivSet([1, 2, 3, 4]);
const b = new EquivSet([3, 4, 5]);
assert.deepEqual(difference(a, b), new EquivSet([1, 2]));
it("array (numbers)", () => {
const a = new ArraySet([1, 2, 3, 4]);
const b = new ArraySet([3, 4, 5]);
assert.deepEqual(difference(a, b), new ArraySet([1, 2]));
});

it("native (obj)", () => {
Expand All @@ -27,9 +27,9 @@ describe("difference", () => {
assert.notStrictEqual(d, b);
});

it("equiv (obj)", () => {
const a = new EquivSet([{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]);
const b = new EquivSet([{ a: 3 }, { a: 4 }, { a: 5 }]);
it("array (obj)", () => {
const a = new ArraySet([{ a: 1 }, { a: 2 }, { a: 3 }, { a: 4 }]);
const b = new ArraySet([{ a: 3 }, { a: 4 }, { a: 5 }]);
const d = difference(a, b);
assert.equal(d.size, 2);
assert.deepEqual(d, new Set([{ a: 1 }, { a: 2 }]));
Expand Down
Loading

0 comments on commit 8756027

Please sign in to comment.