diff options
author | Julian Schurhammer <julian.schurhammer@gmail.com> | 2022-08-13 23:46:10 +1200 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2023-03-13 10:48:58 +0000 |
commit | aae3caf4257adb202d6a6dbabc01dae9dad002c3 (patch) | |
tree | 904e10945c492e8d560cc18cbfe5f676bc2ada4b | |
parent | 507b28c8557af2f74d6504cd75eb687b1fc96a05 (diff) | |
download | gleam_stdlib-aae3caf4257adb202d6a6dbabc01dae9dad002c3.tar.gz gleam_stdlib-aae3caf4257adb202d6a6dbabc01dae9dad002c3.zip |
js map: refactor into class
-rw-r--r-- | src/gleam_stdlib.mjs | 18 | ||||
-rw-r--r-- | src/persistent-hash-map.mjs | 129 |
2 files changed, 85 insertions, 62 deletions
diff --git a/src/gleam_stdlib.mjs b/src/gleam_stdlib.mjs index 81304fe..64dc1d0 100644 --- a/src/gleam_stdlib.mjs +++ b/src/gleam_stdlib.mjs @@ -15,7 +15,7 @@ import { } from "./gleam/regex.mjs"; import { DecodeError } from "./gleam/dynamic.mjs"; import { Some, None } from "./gleam/option.mjs"; -import * as pmap from "./persistent-hash-map.mjs"; +import PMap from "./persistent-hash-map.mjs"; const Nil = undefined; const NOT_FOUND = {}; @@ -396,7 +396,7 @@ export function regex_scan(regex, string) { } export function new_map() { - return pmap.create(); + return PMap.new(); } export function map_size(map) { @@ -404,15 +404,15 @@ export function map_size(map) { } export function map_to_list(map) { - return List.fromArray(pmap.entries(map)); + return List.fromArray(map.entries()); } export function map_remove(key, map) { - return pmap.remove(map, key); + return map.delete(key); } export function map_get(map, key) { - const value = pmap.getWithDefault(map, key, NOT_FOUND); + const value = map.get(key, NOT_FOUND); if (value === NOT_FOUND) { return new Error(Nil); } @@ -420,7 +420,7 @@ export function map_get(map, key) { } export function map_insert(key, value, map) { - return pmap.set(map, key, value); + return map.set(key, value); } function unsafe_percent_decode(string) { @@ -551,7 +551,7 @@ export function classify_dynamic(data) { return `Tuple of ${data.length} elements`; } else if (BitString.isBitString(data)) { return "BitString"; - } else if (data instanceof pmap.PMap) { + } else if (data instanceof PMap) { return "Map"; } else if (typeof data === "number") { return "Float"; @@ -621,7 +621,7 @@ export function decode_result(data) { } export function decode_map(data) { - return data instanceof pmap.PMap ? new Ok(data) : decoder_error("Map", data); + return data instanceof PMap ? new Ok(data) : decoder_error("Map", data); } export function decode_option(data, decoder) { @@ -638,7 +638,7 @@ export function decode_option(data, decoder) { export function decode_field(value, name) { let error = () => decoder_error_no_classify("field", "nothing"); - if (value instanceof pmap.PMap) { + if (value instanceof PMap) { let entry = map_get(value, name); return entry.isOk() ? entry : error(); } diff --git a/src/persistent-hash-map.mjs b/src/persistent-hash-map.mjs index dc3db31..c3b2d17 100644 --- a/src/persistent-hash-map.mjs +++ b/src/persistent-hash-map.mjs @@ -577,73 +577,96 @@ function forEach(root, fn) { } } /** Extra wrapper to keep track of map size */ -export class PMap { +export default class PMap { + static fromObject(o) { + const keys = Object.keys(o); + let m = PMap.new() + for (let i = 0; i < keys.length; i++) { + const k = keys[i]; + m = m.set(k, o[k]) + } + return m + } + static fromMap(o) { + let m = PMap.new() + o.forEach((v, k) => { + m = m.set(k, v) + }); + return m + } + static new() { + return new PMap(undefined, 0); + } constructor(root, size) { this.root = root; this.size = size; } + get(key, notFound) { + if (this.root === undefined) { + return notFound; + } + const found = find(this.root, 0, getHash(key), key); + if (found === undefined) { + return notFound; + } + return found.v; + } + set(key, val) { + const addedLeaf = { val: false }; + const root = this.root === undefined ? EMPTY : this.root; + const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); + if (newRoot === this.root) { + return this; + } + return new PMap(newRoot, addedLeaf.val ? this.size + 1 : this.size); + } + delete(key) { + if (this.root === undefined) { + return this; + } + const newRoot = without(this.root, 0, getHash(key), key); + if (newRoot === this.root) { + return this; + } + if (newRoot === undefined) { + return PMap.new(); + } + return new PMap(newRoot, this.size - 1); + } + has(key) { + if (this.root === undefined) { + return false; + } + return find(this.root, 0, getHash(key), key) !== undefined; + } + entries() { + if (this.root === undefined) { + return []; + } + const result = []; + this.forEach((v, k) => result.push([k, v])); + return result; + } + forEach(fn) { + forEach(this.root, fn) + } hashCode() { let h = 0; - forEach(this.root, (v, k) => { + this.forEach((v, k) => { h = (h + hashMerge(getHash(v), getHash(k))) | 0; }); return h; } equals(o) { + if(!(o instanceof PMap)) { + return + } let equal = true; - forEach(this.root, (v, k) => { - equal = equal && isEqual(getWithDefault(o, k, !v), v); + this.forEach((v, k) => { + equal = equal && isEqual(o.get(k, !v), v); }); return equal; } } -export function create() { - return new PMap(undefined, 0); -} -export function getWithDefault(map, key, notFound) { - if (map.root === undefined) { - return notFound; - } - const found = find(map.root, 0, getHash(key), key); - if (found === undefined) { - return notFound; - } - return found.v; -} -export function set(map, key, val) { - const addedLeaf = { val: false }; - const root = map.root === undefined ? EMPTY : map.root; - const newRoot = assoc(root, 0, getHash(key), key, val, addedLeaf); - if (newRoot === map.root) { - return map; - } - return new PMap(newRoot, addedLeaf.val ? map.size + 1 : map.size); -} -export function remove(map, key) { - if (map.root === undefined) { - return map; - } - const newRoot = without(map.root, 0, getHash(key), key); - if (newRoot === map.root) { - return map; - } - if (newRoot === undefined) { - return create(); - } - return new PMap(newRoot, map.size - 1); -} -export function has(map, key) { - if (map.root === undefined) { - return false; - } - return find(map.root, 0, getHash(key), key) !== undefined; -} -export function entries(map) { - if (map.root === undefined) { - return []; - } - const result = []; - forEach(map.root, (v, k) => result.push([k, v])); - return result; -} + export function __include_me() {} |