Skip to content

Instantly share code, notes, and snippets.

@Lucifier129
Last active October 12, 2020 11:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Lucifier129/f5af22f193f3bb8883a482b24ffca6b0 to your computer and use it in GitHub Desktop.
Save Lucifier129/f5af22f193f3bb8883a482b24ffca6b0 to your computer and use it in GitHub Desktop.
function pipe<T, A>(a: T[], a1: ListAction<T, A>): A[];
function pipe<T, A, B>(a: T[], a1: ListAction<T, A>, a2: ListAction<A, B>): B[];
function pipe<T, A, B, C>(
a: T[],
a1: ListAction<T, A>,
a2: ListAction<A, B>,
a3: ListAction<B, C>
): C[];
function pipe<T, A, B, C, D>(
a: T[],
a1: ListAction<T, A>,
a2: ListAction<A, B>,
a3: ListAction<B, C>,
a4: ListAction<C, D>
): D[];
function pipe<T, A, B, C, D, E>(
a: T[],
a1: ListAction<T, A>,
a2: ListAction<A, B>,
a3: ListAction<B, C>,
a4: ListAction<C, D>,
a5: ListAction<D, E>
): E[];
function pipe<T>(list: T[], ...actions: ListAction<any, any>[]) {
let result = [];
let TakeMap = new Map<symbol, { total: number; current: number }>();
outer: for (let item of list) {
for (let action of actions) {
switch (action.type) {
case 'Map': {
item = action.fn(item);
break;
}
case 'Filter': {
if (!action.fn(item)) continue outer;
break;
}
case 'Take': {
let info = TakeMap.get(action.id);
if (!info) {
info = {
total: action.num,
current: 0,
};
TakeMap.set(action.id, info);
}
if (info.current >= info.total) continue outer;
info.current += 1;
break;
}
default: {
throw new Error(`Unknown action: ${action}`);
}
}
}
result.push(item);
}
return result;
}
type ListAction<T, U = T> =
| {
type: 'Map';
fn: (value: T) => U;
}
| {
type: 'Filter';
fn: (value: T) => boolean;
}
| {
type: 'Take';
id: symbol;
num: number;
};
const map = <T, U>(fn: (value: T) => U): ListAction<T, U> => {
return {
type: 'Map',
fn,
};
};
const filter = <T>(fn: (value: T) => boolean): ListAction<T> => {
return {
type: 'Filter',
fn,
};
};
const take = <T>(num: number): ListAction<T> => {
return {
type: 'Take',
id: Symbol('Take'),
num,
};
};
const test = pipe(
[1, 2, 3, 4],
map((n) => n * 2),
filter((n) => n > 3),
take(2),
map((n) => `count: ${n}`),
take(1)
);
console.log('test', test);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment