This commit is contained in:
JOLIMAITRE Matthieu 2024-06-15 00:22:28 +02:00
commit 6694c7eb9a
10 changed files with 328 additions and 0 deletions

113
src/lib/Chain.ts Normal file
View file

@ -0,0 +1,113 @@
import { Arr, Function, KeyOfType, Tail } from "./types.ts";
import { map } from "./iter.ts";
export class Chain<T extends Arr> {
run;
constructor(run: () => T) {
this.run = run;
}
static from<T>(value: T) {
return new Chain(() => [value] as [T]);
}
to<A extends Arr, O>(map: Function<[...T, ...A], O>, ...args: A) {
const this_run = this.run;
return new Chain(() => [map(...this_run(), ...args)] as [O]);
}
front<I extends Arr>(...values: I) {
const this_run = this.run;
return new Chain(() => [...values, ...this_run()] as [...I, ...T]);
}
back<I extends Arr>(...values: I) {
const this_run = this.run;
return new Chain(() => [...this_run(), ...values] as [...T, ...I]);
}
nth<Index extends number>(index: Index) {
const this_run = this.run;
return new Chain(() => [this_run()[index]] as T[Index]);
}
call<
A extends Arr,
Arg extends [...Tail<T>, ...A],
M extends KeyOfType<T[0], Function<Arg>>,
O extends ReturnType<T[0][M]>,
>(method: M, ...args: A) {
const this_run = this.run;
return new Chain(() => {
const [instance, ...rest] = this_run();
return [instance[method](...rest, ...args)] as [O];
});
}
call_ignore<
A extends Arr,
Arg extends [...Tail<T>, ...A],
M extends KeyOfType<T[0], Function<Arg>>,
>(method: M, ...args: A) {
const this_run = this.run;
return new Chain(() => {
const res1: T = this_run();
const [instance, ...rest] = res1;
instance[method](...rest, ...args);
return res1;
});
}
call_keep<
A extends Arr,
Arg extends [...Tail<T>, ...A],
M extends KeyOfType<T[0], Function<Arg>>,
O extends ReturnType<T[0][M]>,
>(method: M, ...args: A) {
const this_run = this.run;
return new Chain(() => {
const res1 = this_run();
const [instance, ...rest] = res1;
const res2: O = instance[method](...rest, ...args);
return [...res1, res2] as [...T, O];
});
}
construct<
A extends Arr,
C extends new (...args: [...T, ...A]) => unknown,
O extends InstanceType<C>,
>(class_: C, ...args: A) {
const this_run = this.run;
return new Chain(() => [new class_(...this_run(), ...args)] as [O]);
}
}
Deno.test("example", async () => {
const { assertEquals } = await import("https://deno.land/std@0.224.0/assert/mod.ts");
function times_2(num: number) {
return num * 2;
}
// type: number
const [_o1] = Chain.from(3).to(times_2).run();
// type: number
const [_o2] = Chain.from(3).front(2, 5).to(Math.max).run();
function parse_and_add(text: string, num: number) {
return parseInt(text) + num;
}
// type: string
const [_o3] = Chain.from(3).front("5").to(parse_and_add).call("toString").run();
// type: Set<number>
const [_o4] = Chain.from([1, 2, 3])
.call_keep("push", 7)
.construct(Set<number>)
.call_ignore("add", 8)
.to(map, (item: number) => item.toString())
.run();
assertEquals([..._o4], ["1", "2", "3", "7", "8"]);
});