본문 바로가기
개발/typescript, web

[21-06-23 사내모각코] pipeline에서 각 함수의 결과를 측정하여 처리할 수 있게 하는 작업

by 꾸루루 2021. 6. 23.

pipeline에서의 함수 체이닝시 각각의 결과를 lazy하게 측정하여 해당 결과를 통해 다양한 처리를 할 수 있도록 해봤어요.

어제 말씀드린 카테고리 이론 관련하여 기초적인 내용들 쉽게 작성한 글이 있어서 올려봐요! 지금 보니 제가 설명한게 좀 틀린게 있네욤..

https://evan-moon.github.io/2020/01/27/safety-function-composition/

그리고 제가 한건 그 각 함수가 연결되어 실행하는 로직을 generator함수로 감싸서 lazy하게 실행할 수 있게 하고 밑에 conveyorLogger 같은 lazy한 처리를 관찰하고 처리하는 처리기를 따로 둔 것이 제가 한거에요.

 

예를 들어 중간에 Except가 리턴되면 처리기가 해당 Except를 확인하여 남은 pipeline을 타지 않고 해당하는 코드를 즉시 리턴하게 해줘요.

 

(generator에서 반환되는 yield 타입 추론을 어떻게 해야할까요..? 😢)

 

class Except<T extends string = string> {
constructor(public code: T) {}
}
export const conveyor_belt = <T extends ((a: any) => any | Except)[]>(
fns: [...T]
) => {
return function* (arg: Parameters<T[0]>[0]) {
for (const fn of fns) {
yield fn(arg)
}
}
// no lazy
// return (arg: Parameters<T[0]>[0]) =>
// fns.reduce((output, fn) => fn(output), arg)
}
const myConveyor1 = conveyor_belt([
(str: string) => (str !== '10' ? parseInt(str) : new Except('NO TEN STRING')),
(num: number) =>
num <= 100 ? num * 2 : new Except('MUST NUMBER LESS THEN 100') /*?*/,
(num: number) => [...new Array(10)].map((_, i) => num * i) /*?*/,
])
const myConveyor2 = conveyor_belt([
(a: any) => (typeof a === 'string' ? new Except('string not allowed.') : a),
(a: any) => (typeof a === 'number' ? new Except('number not allowed.') : a),
(a: any) => (typeof a === 'boolean' ? new Except('boolean not allowed.') : a),
])
const conveyorLogger =
<conveyorT extends ReturnType<typeof conveyor_belt>>(con: conveyorT) =>
(arg: any) => {
const iterator = con(arg)
let lastValue: any
while (true) {
const it = iterator.next()
if (it.value instanceof Except) return it.value.code
if (it.done) return lastValue
else {
lastValue = it.value
}
}
}
conveyorLogger(myConveyor1)('5') /*?*/ // [0, 5, 10, 15, 20, 25, 30, 35, 40 ,45]
conveyorLogger(myConveyor1)('10') /*?*/ // "NO TEN STRING"
conveyorLogger(myConveyor1)('102') /*?*/ // "MUST NUMBER LESS THEN 100"
conveyorLogger(myConveyor2)('102') /*?*/ // string not allowed.
conveyorLogger(myConveyor2)(142) /*?*/ // number not allowed.
conveyorLogger(myConveyor2)(true) /*?*/ // boolean not allowed.
conveyorLogger(myConveyor2)(function hihi() {
return 'hihi'
}) /*?*/ // fn hihi