@chris5855/scats
Version:
A comprehensive TypeScript library bringing Scala's powerful functional programming paradigms to JavaScript/TypeScript, featuring immutable collections, monads, pattern matching, and more
2,261 lines (2,254 loc) • 111 kB
JavaScript
// src/Option.ts
var SomeImpl = class {
constructor(value2) {
this.value = value2;
if (value2 === null || value2 === void 0) {
throw new Error("Cannot create Some with null or undefined value");
}
}
get isSome() {
return true;
}
get isNone() {
return false;
}
get() {
return this.value;
}
getOrElse(_defaultValue) {
return this.value;
}
getOrCall(_f) {
return this.value;
}
getOrThrow(_error) {
return this.value;
}
map(f) {
return Some(f(this.value));
}
mapOr(_defaultValue, f) {
return Some(f(this.value));
}
flatMap(f) {
return f(this.value);
}
orElse(_alternative) {
return this;
}
orCall(_f) {
return this;
}
filter(predicate) {
return predicate(this.value) ? this : None;
}
forEach(f) {
f(this.value);
}
toArray() {
return [this.value];
}
toEither(_left) {
return Right(this.value);
}
match(patterns) {
return patterns.Some(this.value);
}
toString() {
return `Some(${this.value})`;
}
};
var NoneImpl = class {
get isSome() {
return false;
}
get isNone() {
return true;
}
get() {
throw new Error("Cannot get value from None");
}
getOrElse(defaultValue) {
return defaultValue;
}
getOrCall(f) {
return f();
}
getOrThrow(error) {
throw error;
}
map(_f) {
return this;
}
mapOr(defaultValue, _f) {
return Some(defaultValue);
}
flatMap(_f) {
return this;
}
orElse(alternative) {
return alternative;
}
orCall(f) {
return f();
}
filter(_predicate) {
return this;
}
forEach(_f) {
}
toArray() {
return [];
}
toEither(left) {
return Left(left);
}
match(patterns) {
return patterns.None();
}
toString() {
return "None";
}
};
var None = new NoneImpl();
function Some(value2) {
if (value2 === null || value2 === void 0) {
return None;
}
return new SomeImpl(value2);
}
var Option;
((Option10) => {
function fromNullable(value2) {
return value2 === null || value2 === void 0 ? None : Some(value2);
}
Option10.fromNullable = fromNullable;
function tryCatch(f) {
try {
return Some(f());
} catch (e) {
return None;
}
}
Option10.tryCatch = tryCatch;
function firstSome(...options) {
for (const option of options) {
if (option.isSome) return option;
}
return None;
}
Option10.firstSome = firstSome;
function sequence(options) {
const values = [];
for (const option of options) {
if (option.isNone) return None;
values.push(option.get());
}
return Some(values);
}
Option10.sequence = sequence;
function traverse(values, f) {
return sequence(values.map(f));
}
Option10.traverse = traverse;
})(Option || (Option = {}));
function Left(left) {
return {
isLeft: true,
isRight: false,
get: () => {
throw new Error("Cannot get value from Left");
},
getLeft: () => left
};
}
function Right(right) {
return {
isLeft: false,
isRight: true,
get: () => right,
getLeft: () => {
throw new Error("Cannot get left from Right");
}
};
}
// src/Either.ts
var LeftImpl = class {
constructor(value2) {
this.value = value2;
if (value2 === null || value2 === void 0) {
throw new Error("Cannot create Left with null or undefined value");
}
}
get isLeft() {
return true;
}
get isRight() {
return false;
}
get() {
throw new Error("Cannot get Right value from Left");
}
getLeft() {
return this.value;
}
getOrElse(defaultValue) {
return defaultValue;
}
getOrCall(f) {
return f(this.value);
}
getOrThrow(error) {
throw error;
}
map(_f) {
return this;
}
mapLeft(f) {
return Left2(f(this.value));
}
flatMap(_f) {
return this;
}
orElse(alternative) {
return alternative;
}
orCall(f) {
return f(this.value);
}
fold(onLeft, _onRight) {
return onLeft(this.value);
}
forEach(_f) {
}
forEachLeft(f) {
f(this.value);
}
toOption() {
return None;
}
swap() {
return Right2(this.value);
}
match(patterns) {
return patterns.Left(this.value);
}
toString() {
return `Left(${this.value})`;
}
};
var RightImpl = class {
constructor(value2) {
this.value = value2;
if (value2 === null || value2 === void 0) {
throw new Error("Cannot create Right with null or undefined value");
}
}
get isLeft() {
return false;
}
get isRight() {
return true;
}
get() {
return this.value;
}
getLeft() {
throw new Error("Cannot get Left value from Right");
}
getOrElse(_defaultValue) {
return this.value;
}
getOrCall(_f) {
return this.value;
}
getOrThrow(_error) {
return this.value;
}
map(f) {
return Right2(f(this.value));
}
mapLeft(_f) {
return this;
}
flatMap(f) {
return f(this.value);
}
orElse(_alternative) {
return this;
}
orCall(_f) {
return this;
}
fold(_onLeft, onRight) {
return onRight(this.value);
}
forEach(f) {
f(this.value);
}
forEachLeft(_f) {
}
toOption() {
return Some(this.value);
}
swap() {
return Left2(this.value);
}
match(patterns) {
return patterns.Right(this.value);
}
toString() {
return `Right(${this.value})`;
}
};
function Left2(left) {
if (left === null || left === void 0) {
throw new Error("Cannot create Left with null or undefined value");
}
return new LeftImpl(left);
}
function Right2(right) {
if (right === null || right === void 0) {
throw new Error("Cannot create Right with null or undefined value");
}
return new RightImpl(right);
}
var Either;
((Either4) => {
function tryCatch(f) {
try {
return Right2(f());
} catch (e) {
return Left2(e);
}
}
Either4.tryCatch = tryCatch;
function sequence(eithers) {
const values = [];
for (const either of eithers) {
if (either.isLeft) return either;
values.push(either.get());
}
return Right2(values);
}
Either4.sequence = sequence;
function traverse(values, f) {
return sequence(values.map(f));
}
Either4.traverse = traverse;
})(Either || (Either = {}));
// src/Try.ts
var SuccessImpl = class _SuccessImpl {
constructor(value2) {
this.value = value2;
}
get isSuccess() {
return true;
}
get isFailure() {
return false;
}
get() {
return this.value;
}
getOrElse(_defaultValue) {
return this.value;
}
getError() {
throw new Error("Cannot get error from Success");
}
failed() {
return new FailureImpl(new Error("Success has no failure"));
}
map(f) {
try {
return new _SuccessImpl(f(this.value));
} catch (e) {
return new FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
flatMap(f) {
try {
return f(this.value);
} catch (e) {
return new FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
recover(_f) {
return this;
}
recoverWith(_f) {
return this;
}
transform(s, _f) {
try {
return s(this.value);
} catch (e) {
return new FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
toOption() {
return Some(this.value);
}
toEither() {
return Right2(this.value);
}
fold(_onFailure, onSuccess) {
return onSuccess(this.value);
}
match(patterns) {
return patterns.Success(this.value);
}
toString() {
return `Success(${this.value})`;
}
};
var FailureImpl = class _FailureImpl {
constructor(error) {
this.error = error;
}
get isSuccess() {
return false;
}
get isFailure() {
return true;
}
get() {
throw this.error;
}
getOrElse(defaultValue) {
return defaultValue;
}
getError() {
return this.error;
}
failed() {
return new SuccessImpl(this.error);
}
map(_f) {
return this;
}
flatMap(_f) {
return this;
}
recover(f) {
try {
return new SuccessImpl(f(this.error));
} catch (e) {
return new _FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
recoverWith(f) {
try {
return f(this.error);
} catch (e) {
return new _FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
transform(_s, f) {
try {
return f(this.error);
} catch (e) {
return new _FailureImpl(e instanceof Error ? e : new Error(String(e)));
}
}
toOption() {
return None;
}
toEither() {
return Left2(this.error);
}
fold(onFailure, _onSuccess) {
return onFailure(this.error);
}
match(patterns) {
return patterns.Failure(this.error);
}
toString() {
return `Failure(${this.error})`;
}
};
function Success(value2) {
return new SuccessImpl(value2);
}
function Failure(error) {
return new FailureImpl(error);
}
var Try;
((Try4) => {
function of(f) {
try {
return Success(f());
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
}
Try4.of = of;
function sequence(tries) {
const values = [];
for (const t of tries) {
if (t.isFailure) return t;
values.push(t.get());
}
return Success(values);
}
Try4.sequence = sequence;
function traverse(values, f) {
return sequence(values.map(f));
}
Try4.traverse = traverse;
})(Try || (Try = {}));
var TryAsyncImpl = class _TryAsyncImpl {
constructor(promise) {
this.promise = promise;
}
map(f) {
return new _TryAsyncImpl(
this.promise.then(async (result) => {
if (result.isFailure) return result;
try {
const value2 = await f(result.get());
return Success(value2);
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
})
);
}
flatMap(f) {
return new _TryAsyncImpl(
this.promise.then(async (result) => {
if (result.isFailure) return result;
try {
const tryAsync = await f(result.get());
return await tryAsync.toPromise().then(Success).catch(
(e) => Failure(e instanceof Error ? e : new Error(String(e)))
);
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
})
);
}
recover(f) {
return new _TryAsyncImpl(
this.promise.then(async (result) => {
if (result.isSuccess) return result;
try {
const value2 = await f(result.getError());
return Success(value2);
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
})
);
}
recoverWith(f) {
return new _TryAsyncImpl(
this.promise.then(async (result) => {
if (result.isSuccess) return result;
try {
const tryAsync = await f(result.getError());
return await tryAsync.toPromise().then(
(value2) => Success(value2)
).catch(
(e) => Failure(e instanceof Error ? e : new Error(String(e)))
);
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
})
);
}
async toPromise() {
const result = await this.promise;
if (result.isSuccess) {
return result.get();
} else {
throw result.getError();
}
}
};
var TryAsync;
((TryAsync2) => {
function of(f) {
return new TryAsyncImpl(
Promise.resolve().then(async () => {
try {
const value2 = await f();
return Success(value2);
} catch (e) {
return Failure(e instanceof Error ? e : new Error(String(e)));
}
})
);
}
TryAsync2.of = of;
function success(value2) {
return new TryAsyncImpl(Promise.resolve(Success(value2)));
}
TryAsync2.success = success;
function failure(error) {
return new TryAsyncImpl(Promise.resolve(Failure(error)));
}
TryAsync2.failure = failure;
function fromPromise(promise) {
return of(() => promise);
}
TryAsync2.fromPromise = fromPromise;
})(TryAsync || (TryAsync = {}));
// src/ExecutionContext.ts
var GlobalExecutionContext = class {
/**
* Executes a task asynchronously.
*/
execute(task) {
setTimeout(task, 0);
}
/**
* Reports a failure to the console.
*/
reportFailure(cause) {
console.error("Execution context failure:", cause);
}
};
var SynchronousExecutionContext = class {
/**
* Executes a task immediately in the current thread.
*/
execute(task) {
task();
}
/**
* Reports a failure to the console.
*/
reportFailure(cause) {
console.error("Execution context failure:", cause);
}
};
var ExecutionContext = {
/**
* The global execution context.
*/
global: new GlobalExecutionContext(),
/**
* A synchronous execution context for testing.
*/
synchronous: new SynchronousExecutionContext(),
/**
* Creates an execution context from a function that executes tasks.
*/
fromExecutor(executor, reporter = console.error) {
return {
execute: executor,
reportFailure: reporter
};
}
};
// src/List.ts
var EmptyList = class {
get isEmpty() {
return true;
}
get size() {
return 0;
}
head() {
throw new Error("Cannot get head of empty list");
}
tail() {
throw new Error("Cannot get tail of empty list");
}
headOption() {
return None;
}
tailOption() {
return None;
}
prepend(element) {
return new ConsImpl(element, this);
}
append(element) {
return new ConsImpl(element, this);
}
concat(that) {
return that;
}
map(_f) {
return empty();
}
flatMap(_f) {
return empty();
}
filter(_predicate) {
return this;
}
partition(_predicate) {
return [this, this];
}
exists(_predicate) {
return false;
}
forAll(_predicate) {
return true;
}
foldLeft(initial, _f) {
return initial;
}
foldRight(initial, _f) {
return initial;
}
forEach(_f) {
}
slice(_start, _end) {
return this;
}
take(_n) {
return this;
}
drop(_n) {
return this;
}
takeWhile(_predicate) {
return this;
}
dropWhile(_predicate) {
return this;
}
get(_index) {
throw new Error("Index out of bounds");
}
getOption(_index) {
return None;
}
updateAt(_index, _element) {
return this;
}
indexOf(_element) {
return -1;
}
contains(_element) {
return false;
}
distinct() {
return this;
}
reverse() {
return this;
}
sorted(_compareFn) {
return this;
}
toArray() {
return [];
}
toString() {
return "List()";
}
*[Symbol.iterator]() {
}
};
var ConsImpl = class _ConsImpl {
constructor(_head, _tail) {
this._head = _head;
this._tail = _tail;
}
get isEmpty() {
return false;
}
get size() {
let size = 1;
let current = this._tail;
while (!current.isEmpty) {
size += 1;
current = current.tail();
}
return size;
}
head() {
return this._head;
}
tail() {
return this._tail;
}
headOption() {
return Some(this._head);
}
tailOption() {
return Some(this._tail);
}
prepend(element) {
return new _ConsImpl(element, this);
}
append(element) {
return this.concat(List.of(element));
}
concat(that) {
if (that.isEmpty) return this;
let reversed = empty();
let current = this;
while (!current.isEmpty) {
reversed = reversed.prepend(current.head());
current = current.tail();
}
let result = that;
current = reversed;
while (!current.isEmpty) {
result = result.prepend(current.head());
current = current.tail();
}
return result;
}
map(f) {
const result = [];
let current = this;
while (!current.isEmpty) {
result.push(f(current.head()));
current = current.tail();
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
flatMap(f) {
let result = empty();
const elements = [];
let current = this;
while (!current.isEmpty) {
elements.push(f(current.head()));
current = current.tail();
}
for (let i = elements.length - 1; i >= 0; i--) {
result = elements[i].concat(result);
}
return result;
}
filter(predicate) {
const result = [];
let current = this;
while (!current.isEmpty) {
const head = current.head();
if (predicate(head)) {
result.push(head);
}
current = current.tail();
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
partition(predicate) {
const trueResults = [];
const falseResults = [];
let current = this;
while (!current.isEmpty) {
const head = current.head();
if (predicate(head)) {
trueResults.push(head);
} else {
falseResults.push(head);
}
current = current.tail();
}
let trueList = empty();
for (let i = trueResults.length - 1; i >= 0; i--) {
trueList = trueList.prepend(trueResults[i]);
}
let falseList = empty();
for (let i = falseResults.length - 1; i >= 0; i--) {
falseList = falseList.prepend(falseResults[i]);
}
return [trueList, falseList];
}
exists(predicate) {
let current = this;
while (!current.isEmpty) {
if (predicate(current.head())) {
return true;
}
current = current.tail();
}
return false;
}
forAll(predicate) {
let current = this;
while (!current.isEmpty) {
if (!predicate(current.head())) {
return false;
}
current = current.tail();
}
return true;
}
foldLeft(initial, f) {
let result = initial;
let current = this;
while (!current.isEmpty) {
result = f(result, current.head());
current = current.tail();
}
return result;
}
foldRight(initial, f) {
const reversed = this.reverse();
return reversed.foldLeft(initial, (acc, a) => f(a, acc));
}
forEach(f) {
let current = this;
while (!current.isEmpty) {
f(current.head());
current = current.tail();
}
}
slice(start, end) {
const endIndex = end === void 0 ? this.size : end;
return this.take(endIndex).drop(start);
}
take(n) {
if (n <= 0) return empty();
const result = [];
let current = this;
let count = 0;
while (!current.isEmpty && count < n) {
result.push(current.head());
current = current.tail();
count += 1;
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
drop(n) {
if (n <= 0) return this;
let current = this;
let count = 0;
while (!current.isEmpty && count < n) {
current = current.tail();
count += 1;
}
return current;
}
takeWhile(predicate) {
const result = [];
let current = this;
while (!current.isEmpty) {
const head = current.head();
if (!predicate(head)) break;
result.push(head);
current = current.tail();
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
dropWhile(predicate) {
let current = this;
while (!current.isEmpty) {
if (!predicate(current.head())) {
return current;
}
current = current.tail();
}
return empty();
}
get(index) {
if (index < 0) {
throw new Error("Index out of bounds");
}
let current = this;
let currentIndex = 0;
while (!current.isEmpty) {
if (currentIndex === index) {
return current.head();
}
current = current.tail();
currentIndex += 1;
}
throw new Error("Index out of bounds");
}
getOption(index) {
if (index < 0) {
return None;
}
let current = this;
let currentIndex = 0;
while (!current.isEmpty) {
if (currentIndex === index) {
return Some(current.head());
}
current = current.tail();
currentIndex += 1;
}
return None;
}
updateAt(index, element) {
if (index < 0) {
return this;
}
const result = [];
let current = this;
let currentIndex = 0;
let found = false;
while (!current.isEmpty) {
if (currentIndex === index) {
result.push(element);
found = true;
} else {
result.push(current.head());
}
current = current.tail();
currentIndex += 1;
}
if (!found) {
return this;
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
indexOf(element) {
let current = this;
let currentIndex = 0;
while (!current.isEmpty) {
if (current.head() === element) {
return currentIndex;
}
current = current.tail();
currentIndex += 1;
}
return -1;
}
contains(element) {
return this.indexOf(element) !== -1;
}
distinct() {
const seen = /* @__PURE__ */ new Set();
const result = [];
let current = this;
while (!current.isEmpty) {
const head = current.head();
if (!seen.has(head)) {
seen.add(head);
result.push(head);
}
current = current.tail();
}
let listResult = empty();
for (let i = result.length - 1; i >= 0; i--) {
listResult = listResult.prepend(result[i]);
}
return listResult;
}
reverse() {
let result = empty();
let current = this;
while (!current.isEmpty) {
result = result.prepend(current.head());
current = current.tail();
}
return result;
}
sorted(compareFn) {
const array2 = this.toArray();
array2.sort(compareFn);
let result = empty();
for (let i = array2.length - 1; i >= 0; i--) {
result = result.prepend(array2[i]);
}
return result;
}
toArray() {
const result = [];
let current = this;
while (!current.isEmpty) {
result.push(current.head());
current = current.tail();
}
return result;
}
toString() {
return `List(${this.toArray().join(", ")})`;
}
*[Symbol.iterator]() {
let current = this;
while (!current.isEmpty) {
yield current.head();
current = current.tail();
}
}
};
function empty() {
return new EmptyList();
}
var List;
((List2) => {
function of(...elements) {
let result = empty3();
for (let i = elements.length - 1; i >= 0; i--) {
result = result.prepend(elements[i]);
}
return result;
}
List2.of = of;
function fromArray(array2) {
return of(...array2);
}
List2.fromArray = fromArray;
function fromIterable(iterable) {
return fromArray([...iterable]);
}
List2.fromIterable = fromIterable;
function empty3() {
return new EmptyList();
}
List2.empty = empty3;
function fill(n, f) {
const array2 = Array(n).fill(null).map((_, i) => f(i));
return fromArray(array2);
}
List2.fill = fill;
function repeat(element, n) {
return fill(n, () => element);
}
List2.repeat = repeat;
function range(start, end, step = 1) {
if (step === 0) {
throw new Error("Step cannot be 0");
}
const array2 = [];
if (step > 0) {
for (let i = start; i < end; i += step) {
array2.push(i);
}
} else {
for (let i = start; i > end; i += step) {
array2.push(i);
}
}
return fromArray(array2);
}
List2.range = range;
function zip(as, bs) {
const result = [];
let currA = as;
let currB = bs;
while (!currA.isEmpty && !currB.isEmpty) {
result.push([currA.head(), currB.head()]);
currA = currA.tail();
currB = currB.tail();
}
return fromArray(result);
}
List2.zip = zip;
function map2(as, bs, f) {
return zip(as, bs).map(([a, b]) => f(a, b));
}
List2.map2 = map2;
})(List || (List = {}));
// src/Map.ts
var MapImpl = class _MapImpl {
constructor(entries) {
this._map = new globalThis.Map(entries);
}
get isEmpty() {
return this._map.size === 0;
}
get size() {
return this._map.size;
}
get keys() {
return List.fromIterable(this._map.keys());
}
get values() {
return List.fromIterable(this._map.values());
}
get entries() {
return List.fromIterable(this._map.entries());
}
get(key) {
return this._map.has(key) ? Some(this._map.get(key)) : None;
}
getOrElse(key, defaultValue) {
return this._map.has(key) ? this._map.get(key) : defaultValue;
}
set(key, value2) {
const newMap = new globalThis.Map(this._map);
newMap.set(key, value2);
return new _MapImpl(newMap);
}
setAll(entries) {
const newMap = new globalThis.Map(this._map);
for (const [key, value2] of entries) {
newMap.set(key, value2);
}
return new _MapImpl(newMap);
}
remove(key) {
if (!this._map.has(key)) {
return this;
}
const newMap = new globalThis.Map(this._map);
newMap.delete(key);
return new _MapImpl(newMap);
}
removeAll(keys) {
const newMap = new globalThis.Map(this._map);
for (const key of keys) {
newMap.delete(key);
}
return new _MapImpl(newMap);
}
update(key, f) {
if (!this._map.has(key)) {
return this;
}
const newMap = new globalThis.Map(this._map);
newMap.set(key, f(this._map.get(key)));
return new _MapImpl(newMap);
}
updateOrSet(key, f) {
const newMap = new globalThis.Map(this._map);
const currentValue = this._map.has(key) ? Some(this._map.get(key)) : None;
newMap.set(key, f(currentValue));
return new _MapImpl(newMap);
}
merge(that) {
return this.setAll(that.entries.toArray());
}
map(f) {
const newEntries = [];
this._map.forEach((value2, key) => {
newEntries.push([key, f(value2, key)]);
});
return new _MapImpl(newEntries);
}
filter(predicate) {
const newEntries = [];
this._map.forEach((value2, key) => {
if (predicate(value2, key)) {
newEntries.push([key, value2]);
}
});
return new _MapImpl(newEntries);
}
exists(predicate) {
for (const [key, value2] of this._map.entries()) {
if (predicate(value2, key)) {
return true;
}
}
return false;
}
forAll(predicate) {
for (const [key, value2] of this._map.entries()) {
if (!predicate(value2, key)) {
return false;
}
}
return true;
}
foldLeft(initial, f) {
let result = initial;
this._map.forEach((value2, key) => {
result = f(result, value2, key);
});
return result;
}
forEach(f) {
this._map.forEach((value2, key) => {
f(value2, key);
});
}
has(key) {
return this._map.has(key);
}
toNativeMap() {
return new globalThis.Map(this._map);
}
toString() {
if (this.isEmpty) {
return "Map()";
}
const entries = Array.from(this._map.entries()).map(([key, value2]) => `[${String(key)}, ${String(value2)}]`).join(", ");
return `Map(${entries})`;
}
};
var Map2;
((Map3) => {
function of(entries) {
return new MapImpl(entries);
}
Map3.of = of;
function fromList(entries) {
return of(entries.toArray());
}
Map3.fromList = fromList;
function fromNativeMap(map) {
return of(map.entries());
}
Map3.fromNativeMap = fromNativeMap;
function empty3() {
return new MapImpl();
}
Map3.empty = empty3;
function fromKeys(keys, f) {
return fromList(keys.map((key) => [key, f(key)]));
}
Map3.fromKeys = fromKeys;
function fromValues(values, f) {
return fromList(values.map((value2) => [f(value2), value2]));
}
Map3.fromValues = fromValues;
})(Map2 || (Map2 = {}));
// src/Set.ts
var SetImpl = class _SetImpl {
constructor(elements) {
this._set = new globalThis.Set(elements);
}
get isEmpty() {
return this._set.size === 0;
}
get size() {
return this._set.size;
}
get values() {
return List.fromIterable(this._set.values());
}
contains(element) {
return this._set.has(element);
}
add(element) {
if (this._set.has(element)) {
return this;
}
const newSet = new globalThis.Set(this._set);
newSet.add(element);
return new _SetImpl(newSet);
}
addAll(elements) {
const newSet = new globalThis.Set(this._set);
let changed = false;
for (const element of elements) {
if (!this._set.has(element)) {
newSet.add(element);
changed = true;
}
}
return changed ? new _SetImpl(newSet) : this;
}
remove(element) {
if (!this._set.has(element)) {
return this;
}
const newSet = new globalThis.Set(this._set);
newSet.delete(element);
return new _SetImpl(newSet);
}
removeAll(elements) {
const newSet = new globalThis.Set(this._set);
let changed = false;
for (const element of elements) {
if (this._set.has(element)) {
newSet.delete(element);
changed = true;
}
}
return changed ? new _SetImpl(newSet) : this;
}
union(that) {
if (that.isEmpty) {
return this;
}
if (this.isEmpty) {
return that;
}
return this.addAll(that.toArray());
}
intersection(that) {
if (this.isEmpty || that.isEmpty) {
return empty2();
}
const newSet = new globalThis.Set();
for (const element of this._set) {
if (that.contains(element)) {
newSet.add(element);
}
}
return new _SetImpl(newSet);
}
difference(that) {
if (this.isEmpty) {
return empty2();
}
if (that.isEmpty) {
return this;
}
return this.removeAll(that.toArray());
}
isSubsetOf(that) {
if (this.isEmpty) {
return true;
}
if (this.size > that.size) {
return false;
}
return this.forAll((element) => that.contains(element));
}
isProperSubsetOf(that) {
return this.size < that.size && this.isSubsetOf(that);
}
isSupersetOf(that) {
return that.isSubsetOf(this);
}
isProperSupersetOf(that) {
return that.isProperSubsetOf(this);
}
map(f) {
const newSet = new globalThis.Set();
this._set.forEach((element) => {
newSet.add(f(element));
});
return new _SetImpl(newSet);
}
filter(predicate) {
const newSet = new globalThis.Set();
this._set.forEach((element) => {
if (predicate(element)) {
newSet.add(element);
}
});
return new _SetImpl(newSet);
}
exists(predicate) {
for (const element of this._set) {
if (predicate(element)) {
return true;
}
}
return false;
}
forAll(predicate) {
for (const element of this._set) {
if (!predicate(element)) {
return false;
}
}
return true;
}
foldLeft(initial, f) {
let result = initial;
this._set.forEach((element) => {
result = f(result, element);
});
return result;
}
forEach(f) {
this._set.forEach((element) => {
f(element);
});
}
partition(predicate) {
const trueSet = new globalThis.Set();
const falseSet = new globalThis.Set();
this._set.forEach((element) => {
if (predicate(element)) {
trueSet.add(element);
} else {
falseSet.add(element);
}
});
return [new _SetImpl(trueSet), new _SetImpl(falseSet)];
}
toNativeSet() {
return new globalThis.Set(this._set);
}
toArray() {
return Array.from(this._set);
}
toString() {
if (this.isEmpty) {
return "Set()";
}
return `Set(${this.toArray().join(", ")})`;
}
};
function empty2() {
return new SetImpl();
}
var Set2;
((Set3) => {
function of(...elements) {
return new SetImpl(elements);
}
Set3.of = of;
function fromIterable(iterable) {
return new SetImpl(iterable);
}
Set3.fromIterable = fromIterable;
function fromNativeSet(set) {
return new SetImpl(set);
}
Set3.fromNativeSet = fromNativeSet;
function empty3() {
return new SetImpl();
}
Set3.empty = empty3;
})(Set2 || (Set2 = {}));
// src/collections/Iterable.ts
var AbstractIterable = class {
[Symbol.iterator]() {
return this.iterator();
}
forEach(f) {
for (const a of this) {
f(a);
}
}
map(f) {
return new MappedIterable(this, f);
}
flatMap(f) {
return new FlatMappedIterable(this, f);
}
collect(f) {
return new CollectedIterable(this, f);
}
concat(other) {
return new ConcatenatedIterable(this, other);
}
filter(p) {
return new FilteredIterable(this, p);
}
filterNot(p) {
return this.filter((a) => !p(a));
}
withFilter(p) {
return this.filter(p);
}
head() {
const iterator = this.iterator();
const result = iterator.next();
if (result.done) {
throw new Error("Collection is empty");
}
return result.value;
}
headOption() {
const iterator = this.iterator();
const result = iterator.next();
return result.done ? None : Some(result.value);
}
last() {
let last;
let hasElements = false;
for (const a of this) {
last = a;
hasElements = true;
}
if (!hasElements) {
throw new Error("Collection is empty");
}
return last;
}
lastOption() {
let last;
let hasElements = false;
for (const a of this) {
last = a;
hasElements = true;
}
return hasElements ? Some(last) : None;
}
find(p) {
for (const a of this) {
if (p(a)) {
return Some(a);
}
}
return None;
}
tail() {
const iterator = this.iterator();
const result = iterator.next();
if (result.done) {
throw new Error("Collection is empty");
}
return new TailIterable(this);
}
init() {
if (this.isEmpty()) {
throw new Error("Collection is empty");
}
return new InitIterable(this);
}
slice(from, to) {
return new SlicedIterable(this, from, to);
}
take(n) {
return new TakenIterable(this, n);
}
drop(n) {
return new DroppedIterable(this, n);
}
takeWhile(p) {
return new TakeWhileIterable(this, p);
}
dropWhile(p) {
return new DropWhileIterable(this, p);
}
takeRight(n) {
return new TakeRightIterable(this, n);
}
dropRight(n) {
return new DropRightIterable(this, n);
}
splitAt(n) {
return [this.take(n), this.drop(n)];
}
span(p) {
return [this.takeWhile(p), this.dropWhile(p)];
}
partition(p) {
return [this.filter(p), this.filterNot(p)];
}
groupBy(f) {
const map = new globalThis.Map();
for (const a of this) {
const key = f(a);
const group = map.get(key) || [];
group.push(a);
map.set(key, group);
}
const result = new globalThis.Map();
for (const [key, values] of map.entries()) {
result.set(key, new ArrayIterable(values));
}
return result;
}
forall(p) {
for (const a of this) {
if (!p(a)) {
return false;
}
}
return true;
}
exists(p) {
for (const a of this) {
if (p(a)) {
return true;
}
}
return false;
}
count(p) {
let count = 0;
for (const a of this) {
if (p(a)) {
count++;
}
}
return count;
}
foldLeft(z, op) {
let result = z;
for (const a of this) {
result = op(result, a);
}
return result;
}
foldRight(z, op) {
const array2 = this.toArray();
let result = z;
for (let i = array2.length - 1; i >= 0; i--) {
result = op(array2[i], result);
}
return result;
}
reduceLeft(op) {
const iterator = this.iterator();
const first = iterator.next();
if (first.done) {
throw new Error("Collection is empty");
}
let result = first.value;
let hasStarted = false;
for (const a of this) {
if (!hasStarted) {
hasStarted = true;
continue;
}
result = op(result, a);
}
return result;
}
reduceRight(op) {
const array2 = this.toArray();
if (array2.length === 0) {
throw new Error("Collection is empty");
}
let result = array2[array2.length - 1];
for (let i = array2.length - 2; i >= 0; i--) {
result = op(array2[i], result);
}
return result;
}
sum() {
return this.foldLeft(0, (sum, a) => {
if (typeof a !== "number") {
throw new Error("Collection contains non-numeric values");
}
return sum + a;
});
}
product() {
return this.foldLeft(1, (prod, a) => {
if (typeof a !== "number") {
throw new Error("Collection contains non-numeric values");
}
return prod * a;
});
}
min() {
if (this.isEmpty()) {
throw new Error("Collection is empty");
}
let min;
let first = true;
for (const a of this) {
if (first || a < min) {
min = a;
first = false;
}
}
return min;
}
max() {
if (this.isEmpty()) {
throw new Error("Collection is empty");
}
let max;
let first = true;
for (const a of this) {
if (first || a > max) {
max = a;
first = false;
}
}
return max;
}
minOption() {
if (this.isEmpty()) {
return None;
}
return Some(this.min());
}
maxOption() {
if (this.isEmpty()) {
return None;
}
return Some(this.max());
}
mkString(start = "", sep = "", end = "") {
const elements = this.toArray();
return start + elements.join(sep) + end;
}
zip(other) {
return new ZippedIterable(this, other);
}
zipAll(other, thisElem, thatElem) {
return new ZipAllIterable(this, other, thisElem, thatElem);
}
zipWithIndex() {
return new ZipWithIndexIterable(this);
}
isEmpty() {
const result = this.iterator().next();
return !!result.done;
}
nonEmpty() {
return !this.isEmpty();
}
size() {
let count = 0;
for (const _ of this) {
count++;
}
return count;
}
knownSize() {
return -1;
}
sizeCompare(other) {
const thisSize = this.size();
if (typeof other === "number") {
return thisSize - other;
} else {
const otherSize = other.size();
return thisSize - otherSize;
}
}
grouped(size) {
return new GroupedIterator(this, size);
}
sliding(size) {
return new SlidingIterator(this, size);
}
toArray() {
const result = [];
for (const a of this) {
result.push(a);
}
return result;
}
toList() {
return List.of(...this.toArray());
}
toSet() {
return Set2.of(...this.toArray());
}
toMap() {
const entries = [];
for (const a of this) {
if (!Array.isArray(a) || a.length !== 2) {
throw new Error("Collection does not have pairs as elements");
}
entries.push([a[0], a[1]]);
}
return Map2.of(entries);
}
};
var MappedIterable = class extends AbstractIterable {
constructor(source, f) {
super();
this.source = source;
this.f = f;
}
iterator() {
const sourceIterator = this.source.iterator();
return {
next: () => {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: this.f(result.value) };
}
};
}
};
var FlatMappedIterable = class extends AbstractIterable {
constructor(source, f) {
super();
this.source = source;
this.f = f;
}
iterator() {
const sourceIterator = this.source.iterator();
let currentIterator = null;
return {
next: () => {
while (true) {
if (currentIterator === null) {
const sourceResult = sourceIterator.next();
if (sourceResult.done) {
return { done: true, value: void 0 };
}
currentIterator = this.f(sourceResult.value).iterator();
}
const result = currentIterator.next();
if (result.done) {
currentIterator = null;
continue;
}
return { done: false, value: result.value };
}
return { done: true, value: void 0 };
}
};
}
};
var CollectedIterable = class extends AbstractIterable {
constructor(source, f) {
super();
this.source = source;
this.f = f;
}
iterator() {
const sourceIterator = this.source.iterator();
return {
next: () => {
while (true) {
const sourceResult = sourceIterator.next();
if (sourceResult.done) {
return { done: true, value: void 0 };
}
const option = this.f(sourceResult.value);
if (option.isSome) {
return { done: false, value: option.get() };
}
}
return { done: true, value: void 0 };
}
};
}
};
var ConcatenatedIterable = class extends AbstractIterable {
constructor(first, second) {
super();
this.first = first;
this.second = second;
}
iterator() {
const firstIterator = this.first.iterator();
const secondIterator = this.second.iterator();
let firstDone = false;
return {
next: () => {
if (!firstDone) {
const result2 = firstIterator.next();
if (!result2.done) {
return { done: false, value: result2.value };
}
firstDone = true;
}
const result = secondIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: result.value };
}
};
}
};
var FilteredIterable = class extends AbstractIterable {
constructor(source, p) {
super();
this.source = source;
this.p = p;
}
iterator() {
const sourceIterator = this.source.iterator();
return {
next: () => {
while (true) {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
if (this.p(result.value)) {
return { done: false, value: result.value };
}
}
return { done: true, value: void 0 };
}
};
}
};
var TailIterable = class extends AbstractIterable {
constructor(source) {
super();
this.source = source;
}
iterator() {
const sourceIterator = this.source.iterator();
const first = sourceIterator.next();
if (first.done) {
throw new Error("Collection is empty");
}
return {
next: () => {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: result.value };
}
};
}
};
var InitIterable = class extends AbstractIterable {
constructor(source) {
super();
this.source = source;
}
iterator() {
const array2 = this.source.toArray();
if (array2.length === 0) {
throw new Error("Collection is empty");
}
let index = 0;
return {
next: () => {
if (index >= array2.length - 1) {
return { done: true, value: void 0 };
}
return { done: false, value: array2[index++] };
}
};
}
};
var SlicedIterable = class extends AbstractIterable {
constructor(source, from, to) {
super();
this.source = source;
this.from = from;
this.to = to;
}
iterator() {
const array2 = this.source.toArray();
const start = Math.max(0, this.from);
const end = Math.min(array2.length, this.to);
let index = start;
return {
next: () => {
if (index >= end) {
return { done: true, value: void 0 };
}
return { done: false, value: array2[index++] };
}
};
}
};
var TakenIterable = class extends AbstractIterable {
constructor(source, n) {
super();
this.source = source;
this.n = n;
}
iterator() {
const sourceIterator = this.source.iterator();
let count = 0;
return {
next: () => {
if (count >= this.n) {
return { done: true, value: void 0 };
}
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
count++;
return { done: false, value: result.value };
}
};
}
};
var DroppedIterable = class extends AbstractIterable {
constructor(source, n) {
super();
this.source = source;
this.n = n;
}
iterator() {
const sourceIterator = this.source.iterator();
let count = 0;
return {
next: () => {
while (count < this.n) {
const result2 = sourceIterator.next();
if (result2.done) {
return { done: true, value: void 0 };
}
count++;
}
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: result.value };
}
};
}
};
var TakeWhileIterable = class extends AbstractIterable {
constructor(source, p) {
super();
this.source = source;
this.p = p;
}
iterator() {
const sourceIterator = this.source.iterator();
let done = false;
return {
next: () => {
if (done) {
return { done: true, value: void 0 };
}
const result = sourceIterator.next();
if (result.done) {
done = true;
return { done: true, value: void 0 };
}
if (!this.p(result.value)) {
done = true;
return { done: true, value: void 0 };
}
return { done: false, value: result.value };
}
};
}
};
var DropWhileIterable = class extends AbstractIterable {
constructor(source, p) {
super();
this.source = source;
this.p = p;
}
iterator() {
const sourceIterator = this.source.iterator();
let found = false;
return {
next: () => {
if (found) {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: result.value };
}
while (true) {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
if (!this.p(result.value)) {
found = true;
return { done: false, value: result.value };
}
}
return { done: true, value: void 0 };
}
};
}
};
var TakeRightIterable = class extends AbstractIterable {
constructor(source, n) {
super();
this.source = source;
this.n = n;
}
iterator() {
const array2 = this.source.toArray();
const start = Math.max(0, array2.length - this.n);
let index = start;
return {
next: () => {
if (index >= array2.length) {
return { done: true, value: void 0 };
}
return { done: false, value: array2[index++] };
}
};
}
};
var DropRightIterable = class extends AbstractIterable {
constructor(source, n) {
super();
this.source = source;
this.n = n;
}
iterator() {
const array2 = this.source.toArray();
const end = Math.max(0, array2.length - this.n);
let index = 0;
return {
next: () => {
if (index >= end) {
return { done: true, value: void 0 };
}
return { done: false, value: array2[index++] };
}
};
}
};
var ZippedIterable = class extends AbstractIterable {
constructor(first, second) {
super();
this.first = first;
this.second = second;
}
iterator() {
const firstIterator = this.first.iterator();
const secondIterator = this.second.iterator();
return {
next: () => {
const firstResult = firstIterator.next();
const secondResult = secondIterator.next();
if (firstResult.done || secondResult.done) {
return { done: true, value: void 0 };
}
return { done: false, value: [firstResult.value, secondResult.value] };
}
};
}
};
var ZipAllIterable = class extends AbstractIterable {
constructor(first, second, thisElem, thatElem) {
super();
this.first = first;
this.second = second;
this.thisElem = thisElem;
this.thatElem = thatElem;
}
iterator() {
const firstIterator = this.first.iterator();
const secondIterator = this.second.iterator();
let firstDone = false;
let secondDone = false;
return {
next: () => {
const firstResult = firstIterator.next();
const secondResult = secondIterator.next();
if (firstResult.done) {
firstDone = true;
}
if (secondResult.done) {
secondDone = true;
}
if (firstDone && secondDone) {
return { done: true, value: void 0 };
}
const a = firstDone ? this.thisElem : firstResult.value;
const b = secondDone ? this.thatElem : secondResult.value;
return { done: false, value: [a, b] };
}
};
}
};
var ZipWithIndexIterable = class extends AbstractIterable {
constructor(source) {
super();
this.source = source;
}
iterator() {
const sourceIterator = this.source.iterator();
let index = 0;
return {
next: () => {
const result = sourceIterator.next();
if (result.done) {
return { done: true, value: void 0 };
}
return { done: false, value: [result.value, index++] };
}
};
}
};
var GroupedIterator = class extends AbstractIterable {
constructor(source, chunkSize) {
super();
this.buffer = [];
this.isDone = false;
this.sourceIterator = source.iterator();
this.chunkSize = chun