UNPKG

scats

Version:

Useful scala classes in typescript

1,928 lines (1,913 loc) 47.9 kB
'use strict'; class ArrayIterable { [Symbol.iterator]() { let i = 0; const items = this.toArray; return { next() { if (i < items.length) { const value = items[i]; i = i + 1; return { value: value, done: false }; } else { return { value: undefined, done: true }; } } }; } foreach(job) { this.toArray.forEach(x => job(x)); } contains(item) { return this.toArray.indexOf(item) >= 0; } forall(p) { return this.toArray.every(i => p(i)); } exists(p) { return this.toArray.find(i => p(i)) !== undefined; } find(p) { return option(this.toArray.find(i => p(i))); } count(p) { let res = 0; this.toArray.forEach(i => { if (p(i)) { res++; } }); return res; } get isEmpty() { return this.size <= 0; } get nonEmpty() { return !this.isEmpty; } get size() { return this.toArray.length; } reduce(op) { return this.reduceLeft(op); } reduceOption(op) { return this.reduceLeftOption(op); } get headOption() { return this.isEmpty ? none : some(this.head); } get head() { if (this.isEmpty) { throw new Error('head on empty collection'); } else { return this.toArray[0]; } } get lastOption() { return this.isEmpty ? none : some(this.last); } get last() { if (this.isEmpty) { throw new Error('empty.last'); } else { return this.toArray[this.size - 1]; } } reduceLeft(op) { if (this.isEmpty) { throw new Error('empty.reduceLeft'); } const array = this.toArray; let acc = array[0]; if (array.length > 1) { for (let i = 1; i < array.length; i++) { acc = op(acc, array[i]); } } return acc; } reduceLeftOption(op) { return this.isEmpty ? none : some(this.reduceLeft(op)); } foldRight(initial) { return (op) => { return new Collection(this.toArray) .reverse .foldLeft(initial)((a, n) => op(n, a)); }; } reduceRight(op) { if (this.isEmpty) { throw new Error('empty.reduceRight'); } let acc = this.last; const array = this.toArray.reverse(); if (array.length > 1) { for (let i = 1; i < array.length; i++) { acc = op(acc, array[i]); } } return acc; } reduceRightOption(op) { return this.isEmpty ? none : some(this.reduceRight(op)); } foldLeft(initial) { return (op) => { return this.toArray.reduce((a, n) => op(a, n), initial); }; } fold(initial) { return this.foldLeft(initial); } groupBy(field) { return this.foldLeft(HashMap$2.empty)((acc, next) => { const key = field(next); const existing = acc.get(key).getOrElseValue(Collection.empty); return acc.set(key, new Collection(existing.toArray.concat(next))); }); } minBy(toNumber) { if (this.isEmpty) { throw new Error('empty.minBy'); } else { let res = this.head; let min = toNumber(res); this.toArray.forEach(i => { const next = toNumber(i); if (next < min) { res = i; min = next; } }); return res; } } minByOption(toNumber) { return this.isEmpty ? none : some(this.minBy(toNumber)); } maxBy(toNumber) { if (this.isEmpty) { throw new Error('empty.maxBy'); } else { let res = this.head; let max = toNumber(res); this.toArray.forEach(i => { const next = toNumber(i); if (next > max) { res = i; max = next; } }); return res; } } maxByOption(toNumber) { return this.isEmpty ? none : some(this.maxBy(toNumber)); } partition(p) { const array = this.toArray; const first = array.filter(i => p(i)); const second = array.filter(i => !p(i)); return [this.fromArray(first), this.fromArray(second)]; } take(n) { const items = this.toArray; return items.length > n ? this.fromArray(items.slice(0, n)) : this; } takeRight(n) { const array = this.toArray; return array.length > n ? this.fromArray(array.slice(array.length - n, array.length)) : this; } takeWhile(p) { const array = this.toArray; let res = true; let i = 0; for (; res && i < array.length; i++) { res = p(array[i]); } if (res) { return this; } else { return this.take(i - 1); } } drop(n) { const array = this.toArray; if (n >= array.length) { return this.fromArray([]); } else if (n === 0) { return this; } else { return this.fromArray(array.slice(n, array.length)); } } dropRight(n) { const array = this.toArray; if (n >= array.length) { return this.fromArray([]); } else if (n === 0) { return this; } else { return this.fromArray(array.slice(0, array.length - n)); } } dropWhile(p) { const array = this.toArray; let res = true; let i = 0; for (; res && i < array.length; i++) { res = p(array[i]); } if (res) { return this.fromArray([]); } else { return this.drop(i - 1); } } sliding(length, step = 1) { if (this.isEmpty) { return Collection.empty; } else { const itemsSize = this.size; if (itemsSize <= length) { return Collection.of(this); } else { const result = []; let left = 0; let done = false; let right = length; const items = this.toArray; while (!done) { done = right >= itemsSize; result.push(this.fromArray(items.slice(left, right))); left += step; right = left + length; } return new Collection(result); } } } grouped(length) { return this.sliding(length, length); } mkString(separator = '') { return this.toArray.join(separator); } sum(elementToNum) { if (this.isEmpty) { return 0; } else { return this.toArray.reduce((acc, next) => acc + elementToNum(next), 0); } } filter(p) { return this.fromArray(this.toArray.filter(i => p(i))); } filterNot(p) { return this.fromArray(this.toArray.filter(i => !p(i))); } splitAt(n) { return [this.take(n), this.drop(n)]; } span(p) { return [this.takeWhile(p), this.dropWhile(p)]; } get init() { if (this.isEmpty) throw new Error('empty.init'); return this.dropRight(1); } get tail() { if (this.isEmpty) throw new Error('empty.tail'); return this.drop(1); } groupMap(key) { return (value) => { return this.foldLeft(HashMap$2.empty)((acc, next) => { const nextKey = key(next); const existingColl = acc.getOrElse(nextKey, () => Collection.empty); const updatedColl = existingColl.appended(value(next)); return acc.updated(nextKey, updatedColl); }); }; } groupMapReduce(key) { return (value) => { return (reduce) => { return this.foldLeft(HashMap$2.empty)((acc, next) => { const nextKey = key(next); const nextValue = value(next); return acc.updated(nextKey, acc.get(nextKey).map(e => reduce(e, nextValue)).getOrElseValue(nextValue)); }); }; }; } scan(z) { return this.scanLeft(z); } scanLeft(z) { return (op) => { const res = [z]; let acc = z; this.toArray.forEach(i => { acc = op(acc, i); res.push(acc); }); return this.fromArray(res); }; } scanRight(z) { return (op) => { const res = [z]; let acc = z; this.toArray.reverse().forEach(i => { acc = op(acc, i); res.push(acc); }); return this.fromArray(res.reverse()); }; } get zipWithIndex() { const res = []; const array = this.toArray; for (let i = 0; i < array.length; i++) { res.push([array[i], i]); } return new Collection(res); } get tails() { const array = this.toArray; const res = []; for (let i = 0; i <= array.length; i++) { res.push(this.takeRight(array.length - i)); } return new Collection(res); } get inits() { const array = this.toArray; const res = []; for (let i = 0; i <= array.length; i++) { res.push(this.take(array.length - i)); } return new Collection(res); } } class ArrayBackedCollection extends ArrayIterable { checkWithinBounds(lo, hi) { if (lo < 0) throw new Error(`$lo is out of bounds (min 0, max ${this.items.length - 1})`); if (hi > this.size) throw new Error(`$lo is out of bounds (min 0, max ${this.items.length - 1})`); } get reverse() { return this.fromArray(this.items.reverse()); } get toArray() { return this.items; } get(index) { this.checkWithinBounds(index, index + 1); return this.items[index]; } get toSet() { return HashSet$1.of(...this.items); } indexOf(item) { return this.items.indexOf(item); } get distinct() { return this.fromArray(Array.from(new Set(this.items))); } distinctBy(key) { const keys = new Set(); const res = []; this.foreach(item => { const currentKey = key(item); if (!keys.has(currentKey)) { keys.add(currentKey); res.push(item); } }); return this.fromArray(res); } appended(item) { return this.fromArray(this.items.concat([item])); } appendedAll(other) { return this.fromArray(this.items.concat([...other])); } prepended(item) { return this.fromArray([item].concat(this.items)); } prependedAll(other) { return this.fromArray(Array.from(other).concat(this.items)); } concat(other) { return this.appendedAll(other); } slice(from, until) { return this.fromArray(this.items.slice(from, until)); } sort(param) { return this.fromArray(this.items.slice(0).sort(param)); } sortBy(fieldToNumber) { return this.sort(((a, b) => fieldToNumber(a) - fieldToNumber(b))); } get length() { return this.size; } } class Collection extends ArrayBackedCollection { items; constructor(items) { super(); this.items = items; } static empty = new Collection([]); fromArray(array) { if (!array || array.length <= 0) { return Nil; } else { return new Collection(array); } } static of(...items) { return new Collection(items); } static from(elements) { return new Collection(Array.from(elements)); } static fill(len) { return function (elem) { const res = new Array(len); for (let i = 0; i < len; i++) { res[i] = elem(i); } return new Collection(res); }; } map(f) { return new Collection(this.items.map(i => f(i))); } flatMap(f) { let res = []; this.items.forEach(i => { res = res.concat(f(i).items); }); return new Collection(res); } flatMapOption(f) { const res = []; this.items.forEach(i => { f(i).foreach(v => { res.push(v); }); }); return new Collection(res); } async mapPromise(f) { const res = []; for (let i = 0; i < this.items.length; i++) { res.push(await f(this.items[i])); } return new Collection(res); } async mapPromiseAll(f) { return new Collection(await Promise.all(this.items.map(i => f(i)))); } async flatMapPromise(f) { let res = []; for (let i = 0; i < this.items.length; i++) { const item = this.items[i]; res = res.concat((await f(item)).items); } return new Collection(res); } async flatMapPromiseAll(f) { return (await this.mapPromiseAll(f)).flatten(); } flatten() { const res = []; this.items.forEach(i => { if (i instanceof Collection) { res.push(...i.items); } else { res.push(i); } }); return new Collection(res); } get toBuffer() { return new ArrayBuffer(this.items); } toMap(mapper) { return HashMap$2.of(...this.map(mapper).toArray); } zip(that) { const res = []; for (let i = 0; i < Math.min(this.size, that.size); i++) { res.push([this.items[i], that.items[i]]); } return new Collection(res); } zipAll(that, thisElem, thatElem) { const res = []; for (let i = 0; i < Math.max(this.size, that.size); i++) { res.push([ i < this.items.length ? this.items[i] : thisElem, i < that.items.length ? that.items[i] : thatElem ]); } return new Collection(res); } } const Nil = Collection.empty; class ArrayBuffer extends ArrayBackedCollection { items; static get empty() { return new ArrayBuffer([]); } constructor(items = []) { super(); this.items = items; } static of(...elements) { return new ArrayBuffer(elements); } static from(elements) { return new ArrayBuffer(Array.from(elements)); } static fill(len) { return function (elem) { const res = new Array(len); for (let i = 0; i < len; i++) { res[i] = elem(i); } return new ArrayBuffer(res); }; } fromArray(array) { if (!array || array.length <= 0) { return new ArrayBuffer([]); } else { return new ArrayBuffer(array); } } normalized(n) { return Math.min(Math.max(n, 0), this.length); } update(index, element) { this.checkWithinBounds(index, index + 1); this.items[index] = element; } set(index, element) { this.update(index, element); } clear() { this.items.length = 0; } append(element) { this.items.push(element); return this; } appendAll(elements) { this.items.push(...elements); return this; } prepend(element) { this.items.unshift(element); return this; } prependAll(elements) { this.items.unshift(...elements); return this; } insert(idx, element) { this.checkWithinBounds(idx, idx); this.items.splice(idx, 0, element); } insertAll(idx, elements) { this.checkWithinBounds(idx, idx); this.items.splice(idx, 0, ...elements); } remove(index, count = 1) { if (count > 0) { this.checkWithinBounds(index, index + 1); this.items.splice(index, count); } else if (count < 0) { throw new Error('removing negative number of elements: ' + count); } } subtractOne(element) { const i = this.items.indexOf(element); if (i != -1) { this.remove(i); } return this; } subtractAll(elements) { if (elements === this || elements === this.items) { const buf = new ArrayBuffer(Array.from(elements)); buf.foreach(e => this.subtractOne(e)); } else { for (const element of elements) { this.subtractOne(element); } } return this; } sort(compareFn) { this.items.sort(compareFn); return this; } filterInPlace(p) { let i = 0, j = 0; while (i < this.size) { if (p(this.items[i])) { if (i != j) { this.items[j] = this.items[i]; } j += 1; } i += 1; } if (i == j) { return this; } else { return this.takeInPlace(j); } } dropInPlace(n) { this.remove(0, this.normalized(n)); return this; } dropRightInPlace(n) { const norm = this.normalized(n); this.remove(this.length - norm, norm); return this; } takeInPlace(n) { const norm = this.normalized(n); this.remove(norm, this.length - norm); return this; } takeRightInPlace(n) { this.remove(0, this.length - this.normalized(n)); return this; } sliceInPlace(start, end) { return this.takeInPlace(end).dropInPlace(start); } get toCollection() { return new Collection(this.items.slice(0)); } flatMap(f) { let res = []; this.items.forEach(i => { res = res.concat(f(i).items); }); return new ArrayBuffer(res); } flatMapOption(f) { const res = []; this.items.forEach(i => { f(i).foreach(v => { res.push(v); }); }); return new ArrayBuffer(res); } async flatMapPromise(f) { let res = []; for (let i = 0; i < this.items.length; i++) { const item = this.items[i]; res = res.concat((await f(item)).items); } return new ArrayBuffer(res); } map(f) { return new ArrayBuffer(this.items.map(i => f(i))); } async mapPromise(f) { const res = []; for (let i = 0; i < this.items.length; i++) { res.push(await f(this.items[i])); } return new ArrayBuffer(res); } async mapPromiseAll(f) { return new ArrayBuffer(await Promise.all(this.items.map(i => f(i)))); } async flatMapPromiseAll(f) { return (await this.mapPromiseAll(f)).flatten(); } flatten() { const res = []; this.items.forEach(i => { if (i instanceof ArrayBuffer) { res.push(...i.items); } else { res.push(i); } }); return new ArrayBuffer(res); } toMap(mapper) { return HashMap$2.of(...this.map(mapper).toArray); } } class AbstractMap extends ArrayIterable { map; constructor(map) { super(); this.map = map; } get size() { return this.map.size; } get isEmpty() { return this.map.size <= 0; } get(key) { return option(this.map.get(key)); } getOrElse(key, defaultValue) { return this.get(key).getOrElse(defaultValue); } getOrElseValue(key, defaultValue) { return this.get(key).getOrElseValue(defaultValue); } get keySet() { return HashSet$1.of(...Array.from(this.map.keys())); } get keyIterator() { return this.map.keys(); } get keys() { return new Collection(Array.from(this.map.keys())); } get values() { return new Collection(Array.from(this.map.values())); } get valueIterator() { return this.map.values(); } get entries() { return new Collection(Array.from(this.map.entries())); } get entriesIterator() { return this.map.entries(); } containsKey(key) { return this.map.has(key); } get toCollection() { return new Collection(Array.from(this.map.entries())); } get toMap() { return this.map; } get toArray() { return Array.from(this.map.entries()); } } let HashMap$2 = class HashMap extends AbstractMap { map; fromArray(array) { return HashMap.of(...array); } constructor(map) { super(map); this.map = map; } static of(...values) { return new HashMap(new Map(values)); } static from(values) { return HashMap.of(...Array.from(values)); } static empty = new HashMap(new Map()); appendedAll(map) { return this.concat(map); } appended(key, value) { return this.set(key, value); } updated(key, value) { return this.set(key, value); } removed(key) { const next = new Map(this.map); next.delete(key); return new HashMap(next); } removedAll(keys) { const next = new Map(this.map); for (const key of keys) { next.delete(key); } return new HashMap(next); } concat(map) { const mergedMap = new Map([ ...this.entries.toArray, ...map.entries.toArray ]); return new HashMap(mergedMap); } set(key, value) { const next = new Map(this.map); next.set(key, value); return new HashMap(new Map(next)); } updatedWith(key) { const previousValue = this.get(key); return (remappingFunction) => { const nextValue = remappingFunction(previousValue); if (previousValue.isEmpty && nextValue.isEmpty) { return this; } else if (previousValue.isDefined && nextValue.isEmpty) { return this.removed(key); } else { return this.updated(key, nextValue.get); } }; } get toMutable() { return HashMap$1.of(...Array.from(this.map.entries())); } }; class AbstractSet extends ArrayIterable { items; constructor(items) { super(); this.items = items; } contains(item) { return this.items.has(item); } get toArray() { return Array.from(this.items.keys()); } get toCollection() { return new Collection(Array.from(this.items.keys())); } get toSet() { return new Set(this.items); } get isEmpty() { return this.items.size <= 0; } get size() { return this.items.size; } get toBuffer() { return new ArrayBuffer(Array.from(this.items.keys())); } } let HashSet$2 = class HashSet extends AbstractSet { constructor(items = new Set()) { super(items); } static of(...items) { return new HashSet(new Set(items)); } static from(values) { return HashSet.of(...Array.from(values)); } fromArray(array) { return HashSet.of(...array); } add(elem) { const res = this.items.has(elem); if (!res) { this.items.add(elem); return true; } else { return !res; } } addAll(xs) { for (const x of xs) { this.items.add(x); } return this; } subtractAll(xs) { for (const x of xs) { this.items.delete(x); } return this; } remove(elem) { const res = this.items.has(elem); if (res) { this.items.delete(elem); return true; } else { return res; } } filterInPlace(p) { if (this.nonEmpty) { const arr = this.toArray; for (const t of arr) { if (!p(t)) { this.remove(t); } } } return this; } clear() { this.items.clear(); } addOne(elem) { this.add(elem); return this; } subtractOne(elem) { this.remove(elem); return this; } concat(that) { const newSet = new Set([...this.items, ...that]); return new HashSet(newSet); } intersect(that) { return this.filter(x => that.contains(x)); } union(that) { return this.concat(that); } get toImmutable() { return HashSet$1.of(...this.items); } }; let HashSet$1 = class HashSet extends AbstractSet { constructor(items) { super(items); } static empty = new HashSet(new Set()); static of(...items) { return new HashSet(new Set(items)); } static from(elements) { return new HashSet(new Set(elements)); } fromArray(array) { return HashSet.of(...array); } toMap(mapper) { return HashMap$2.of(...this.map(mapper).toArray); } map(f) { return HashSet.of(...Array.from(this.items).map(i => f(i))); } flatMap(f) { const res = new Set(); this.items.forEach(i => f(i).foreach(e => res.add(e))); return new HashSet(res); } concat(that) { return this.appendedAll(that); } union(other) { return this.concat(other); } appended(item) { return this.fromArray(this.toArray.concat([item])); } appendedAll(other) { const res = Array.from(this.items); res.push(...Array.from(other)); return this.fromArray(res); } removed(item) { const res = new Set(Array.from(this.items)); res.delete(item); return new HashSet(res); } removedAll(other) { const res = new Set(Array.from(this.items)); for (const element of other) { res.delete(element); } return new HashSet(res); } intersect(other) { return this.filter(x => other.contains(x)); } get toMutable() { return HashSet$2.of(...this.items); } }; class Option extends ArrayIterable { static when(cond) { return a => { if (cond) { return some(a()); } else { return none; } }; } static useless(cond) { return Option.when(!cond); } fromArray(array) { if (array.length <= 0) { return none; } else { return some(array[0]); } } exists(p) { if (this.isEmpty) { return false; } else { return p(this.get); } } filter(p) { if (this.isEmpty) { return none; } else { return p(this.get) ? this : none; } } filterNot(p) { if (this.isEmpty) { return none; } else { return p(this.get) ? none : this; } } map(f) { return this.isEmpty ? none : some(f(this.get)); } flatMap(p) { return this.isEmpty ? none : p(this.get); } async mapPromise(f) { if (this.isEmpty) { return Promise.resolve(none); } else { return option(await f(this.get)); } } flatMapPromise(f) { if (this.isEmpty) { return Promise.resolve(none); } else { return f(this.get); } } foldValue(ifEmpty) { if (this.isEmpty) { return function () { return ifEmpty(); }; } else { return (f) => { return f(this.get); }; } } forall(p) { return this.isEmpty ? true : p(this.get); } foreach(f) { if (this.nonEmpty) { f(this.get); } } getOrElse(f) { return this.isEmpty ? f() : this.get; } getOrElseValue(other) { return this.isEmpty ? other : this.get; } getOrElseThrow(error) { if (this.isEmpty) { throw error(); } else { return this.get; } } contains(x) { return this.isEmpty ? false : x === this.get; } get isDefined() { return !this.isEmpty; } orElse(alternative) { return this.isEmpty ? alternative() : this; } orElseValue(alternative) { return this.isEmpty ? alternative : this; } get orNull() { return this.isEmpty ? null : this.get; } get orUndefined() { return this.isEmpty ? undefined : this.get; } get toCollection() { return this.isEmpty ? Collection.empty : Collection.of(this.get); } toRight(left) { return this.isEmpty ? new Left(left()) : right(this.get); } toLeft(right) { return this.isEmpty ? new Right(right()) : left(this.get); } get toArray() { return this.isEmpty ? [] : [this.get]; } get toSet() { return this.isEmpty ? HashSet$1.empty : HashSet$1.of(this.get); } match(matcher) { return this.isEmpty ? matcher.none() : matcher.some(this.get); } toMap(mapper) { return this.isEmpty ? HashMap$2.empty : HashMap$2.of(...this.map(mapper).toArray); } } class Some extends Option { value; constructor(value) { super(); this.value = value; } get get() { return this.value; } get isEmpty() { return false; } } class None extends Option { get get() { throw new Error('No such element.'); } get isEmpty() { return true; } } function option(value) { return value === null || typeof value === 'undefined' ? none : some(value); } function some(value) { return new Some(value); } const none = new None(); function identity(x) { return x; } function toErrorConversion(x) { if (x instanceof Error) { return x; } else { return new Error(`${x}`); } } class StepWithFilter { name; f; filter; constructor(name, f, filter) { this.name = name; this.f = f; this.filter = filter; } if(condition) { return new StepWithFilter(this.name, this.f, some(condition)); } invokeStep(state) { const result = this.f(state); return this.filter.filter(() => 'filter' in result).map(filter => { return result.filter(x => { this.name.foreach(name => state[name] = x); return filter(state); }); }).getOrElseValue(result); } } class TaskWithFilter { name; f; filter; constructor(name, f, filter) { this.name = name; this.f = f; this.filter = filter; } if(condition) { return new TaskWithFilter(this.name, this.f, some(condition)); } async invokeStep(state) { const result = await this.f(state); return this.filter.filter(() => 'filter' in result).map(filter => { return result.filter(x => { this.name.foreach(name => state[name] = x); return filter(state); }); }).getOrElseValue(result); } } function step(name, f) { return new StepWithFilter(some(name), f, none); } function task(name, f) { return new TaskWithFilter(some(name), f, none); } function forComprehension(...steps) { return { yield: function (final) { function processStep(stepIdx, acc) { const result = steps[stepIdx].invokeStep(acc); if (stepIdx < steps.length - 1) { return result.flatMap(x => { steps[stepIdx].name.foreach(name => acc[name] = x); return processStep(stepIdx + 1, acc); }); } else { return result.map(x => { steps[stepIdx].name.foreach(name => acc[name] = x); return final(acc); }); } } return processStep(0, {}); } }; } (function (forComprehension) { function promise(...steps) { return { yield: function (final) { async function processStep(stepIdx, acc) { const result = await steps[stepIdx].invokeStep(acc); if (stepIdx < steps.length - 1) { return await result.flatMapPromise(x => { steps[stepIdx].name.foreach(name => acc[name] = x); return processStep(stepIdx + 1, acc); }); } else { return result.map(x => { steps[stepIdx].name.foreach(name => acc[name] = x); return final(acc); }); } } return processStep(0, {}); } }; } forComprehension.promise = promise; })(forComprehension || (forComprehension = {})); class TryLike { async mapPromise(f) { return this.match({ success: r => Try.promise(() => f(r)), failure: () => Promise.resolve(this) }); } flatMapPromise(f) { return this.match({ success: r => f(r), failure: () => Promise.resolve(this) }); } foreach(f) { if (this.isSuccess) { f(this.get); } } tapFailure(f) { return this.match({ success: () => this, failure: e => { try { f(e); return this; } catch (ex) { return failure(ex); } } }); } toEitherWithLeft(f) { return this.match({ success: r => right(r), failure: e => left(f(e)) }); } } class Success extends TryLike { result; isSuccess = true; isFailure = false; constructor(result) { super(); this.result = result; } get toOption() { return some(this.result); } get toEither() { return right(this.result); } map(f) { return success(f(this.result)); } get get() { return this.result; } getOrElse(_) { return this.result; } getOrElseValue(_) { return this.result; } orElse(_) { return this; } match(matcher) { return matcher.success(this.result); } flatMap(f) { try { return f(this.result); } catch (e) { return failure(e); } } filter(p) { try { if (p(this.result)) { return this; } else { return failure(new Error('Predicate does not hold for ' + this.result)); } } catch (e) { return failure(e); } } get failed() { return failure(new Error('Success.failed')); } fold(fa, fb) { try { return fb(this.result); } catch (e) { return fa(e); } } recover(_) { return this; } recoverWith(_) { return this; } transform(s, _) { return this.flatMap(s); } } class Failure extends TryLike { error; isSuccess = false; isFailure = true; constructor(error) { super(); this.error = error; } get toOption() { return none; } get toEither() { return left(this.error); } map(_) { return this; } get get() { throw this.error; } getOrElse(value) { return value(); } getOrElseValue(value) { return value; } orElse(value) { try { return value(); } catch (e) { return failure(e); } } match(matcher) { return matcher.failure(this.error); } flatMap(_) { return this; } filter(_) { return this; } get failed() { return success(this.error); } fold(fa, _) { return fa(this.error); } recover(f) { try { return success(f(this.error)); } catch (ex) { return failure(ex); } } recoverWith(f) { return this.transform(identity, f); } transform(s, f) { try { return f(this.error); } catch (ex) { return failure(ex); } } } function Try(block) { try { return new Success(block()); } catch (e) { return new Failure(e); } } (function (Try) { function promise(block) { try { return block() .then(res => new Success(res)) .catch(e => new Failure(e)); } catch (e) { return Promise.resolve(new Failure(e)); } } Try.promise = promise; })(Try || (Try = {})); function success(x) { return new Success(x); } function failure(x) { return new Failure(x); } class Either { get isRight() { return !this.isLeft; } get left() { return new Either.LeftProjection(this); } fold(fa, fb) { return this.match({ right: v => fb(v), left: e => fa(e) }); } get swap() { return this.match({ right: v => left(v), left: e => right(e) }); } foreach(f) { this.match({ right: b => f(b), left: () => { } }); } getOrElse(or) { return this.match({ right: b => b, left: () => or() }); } getOrElseValue(or) { return this.match({ right: b => b, left: () => or }); } orElse(or) { return this.match({ right: () => this, left: () => or() }); } orElseValue(or) { return this.match({ right: () => this, left: () => or }); } contains(elem) { return this.match({ right: b => elem === b, left: () => false }); } forall(f) { return this.match({ right: b => f(b), left: () => true }); } exists(p) { return this.match({ right: b => p(b), left: () => false }); } flatMap(f) { return this.match({ right: v => f(v), left: () => this }); } flatMapPromise(f) { return this.match({ right: v => f(v), left: () => Promise.resolve(this) }); } map(f) { return this.match({ right: v => right(f(v)), left: () => this }); } async mapPromise(f) { return this.match({ right: async (v) => right(await f(v)), left: () => Promise.resolve(this) }); } filterOrElse(p, zero) { return this.match({ right: (v) => p(v) ? this : left(zero()), left: () => this, }); } filterOrElseValue(p, zero) { return this.match({ right: (v) => p(v) ? this : left(zero), left: () => this, }); } get toCollection() { return this.match({ right: v => Collection.of(v), left: () => Collection.empty }); } get toOption() { return this.match({ right: v => some(v), left: () => none }); } toTry(toError = toErrorConversion) { return this.match({ right: (b) => success(b), left: (e) => failure(toError(e)) }); } } class Left extends Either { error; constructor(error) { super(); this.error = error; } match(matcher) { return matcher.left(this.error); } get isLeft() { return true; } withRight() { return this; } } class Right extends Either { value; constructor(value) { super(); this.value = value; } match(matcher) { return matcher.right(this.value); } get isLeft() { return false; } withLeft() { return this; } } (function (Either) { class LeftProjection { e; constructor(e) { this.e = e; } mapPromise(f) { return this.e.match({ left: async (v) => left(await f(v)), right: () => Promise.resolve(this.e) }); } flatMapPromise(f) { return this.e.match({ left: v => f(v), right: () => Promise.resolve(this.e) }); } foreach(f) { this.e.match({ left: l => f(l), right: () => { } }); } getOrElse(or) { return this.e.match({ left: a => a, right: or }); } getOrElseValue(or) { return this.e.match({ left: a => a, right: () => or }); } forall(p) { return this.e.match({ left: (a) => p(a), right: () => true }); } exists(p) { return this.e.match({ left: (a) => p(a), right: () => false }); } flatMap(f) { return this.e.match({ left: (a) => f(a), right: () => this.e }); } map(f) { return this.e.match({ left: a => left(f(a)), right: () => this.e }); } filterToOption(p) { return this.e.match({ left: l => p(l) ? some(this.e) : none, right: () => none }); } get toCollection() { return this.e.match({ left: l => Collection.of(l), right: () => Nil }); } get toOption() { return this.e.match({ left: l => some(l), right: () => none }); } } Either.LeftProjection = LeftProjection; })(Either || (Either = {})); function right(value) { return new Right(value); } function left(value) { return new Left(value); } let HashMap$1 = class HashMap extends AbstractMap { constructor(map = new Map()) { super(map); } fromArray(array) { return HashMap.of(...array); } static of(...values) { return new HashMap(new Map(values)); } static from(values) { return HashMap.of(...Array.from(values)); } addAll(values) { for (const [key, value] of values) { this.map.set(key, value); } return this; } updateWith(key) { const previousValue = this.get(key); return (remappingFunction) => { const nextValue = remappingFunction(previousValue); if (previousValue.isEmpty && nextValue.isEmpty) { return nextValue; } else if (previousValue.isDefined && nextValue.isEmpty) { this.remove(key); return nextValue; } else { this.update(key, nextValue.get); return nextValue; } }; } subtractAll(values) { if (this.isEmpty) { return this; } for (const key of values) { this.map.delete(key); if (this.isEmpty) { return this; } } return this; } clear() { this.map.clear(); } clone() { const contentClone = new Map(this.map); return new HashMap(contentClone); } filterInPlace(p) { if (this.nonEmpty) { const entries = this.entries; entries.foreach(e => { if (!p(e)) { this.remove(e[0]); } }); } return this; } mapValuesInPlace(f) { if (this.nonEmpty) { const entries = this.entries; entries.foreach(e => { this.update(e[0], f(e)); }); } return this; } getOrElseUpdate(key, defaultValue) { return this.get(key).getOrElse(() => { const newValue = defaultValue(); this.map.set(key, newValue); return newValue; }); } set(key, value) { this.map.set(key, value); return this; } put(key, value) { const res = this.get(key); this.map.set(key, value); return res; } remove(key) { const res = this.get(key); this.subtractOne(key); return res; } update(key, value) { this.map.set(key, value); } addOne(elem) { this.map.set(elem[0], elem[1]); return this; } subtractOne(key) { this.map.delete(key); return this; } get toImmutable() { return HashMap$2.of(...this.map.entries()); } }; var mutable = /*#__PURE__*/Object.freeze({ __proto__: null, ArrayBuffer: ArrayBuffer, HashMap: HashMap$1, HashSet: HashSet$2 }); exports.ArrayBackedCollection = ArrayBackedCollection; exports.ArrayBuffer = ArrayBuffer; exports.Collection = Collection; exports.Either = Either; exports.Failure = Failure; exports.HashMap = HashMap$2; exports.HashSet = HashSet$1; exports.Left = Left; exports.Nil = Nil; exports.None = None; exports.Option = Option; exports.Right = Right; exports.Some = Some; exports.StepWithFilter = StepWithFilter; exports.Success = Success; exports.TaskWithFilter = TaskWithFilter; exports.Try = Try; exports.TryLike = TryLike; exports.failure = failure; exports.forComprehension = forComprehension; exports.identity = identity; exports.left = left; exports.mutable = mutable; exports.none = none; exports.option = option; exports.right = right; exports.some = some; exports.step = step; exports.success = success; exports.task = task; exports.toErrorConversion = toErrorConversion;