scats
Version:
Useful scala classes in typescript
1,928 lines (1,913 loc) • 47.9 kB
JavaScript
'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;