pipeline에서의 함수 체이닝시 각각의 결과를 lazy하게 측정하여 해당 결과를 통해 다양한 처리를 할 수 있도록 해봤어요.
어제 말씀드린 카테고리 이론 관련하여 기초적인 내용들 쉽게 작성한 글이 있어서 올려봐요! 지금 보니 제가 설명한게 좀 틀린게 있네욤..
https://evan-moon.github.io/2020/01/27/safety-function-composition/
그리고 제가 한건 그 각 함수가 연결되어 실행하는 로직을 generator함수로 감싸서 lazy하게 실행할 수 있게 하고 밑에 conveyorLogger 같은 lazy한 처리를 관찰하고 처리하는 처리기를 따로 둔 것이 제가 한거에요.
예를 들어 중간에 Except가 리턴되면 처리기가 해당 Except를 확인하여 남은 pipeline을 타지 않고 해당하는 코드를 즉시 리턴하게 해줘요.
(generator에서 반환되는 yield 타입 추론을 어떻게 해야할까요..? 😢)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
'개발 > typescript, web' 카테고리의 다른 글
[21-07-08 개인스터디] fp-ts: semigroup (0) | 2021.06.27 |
---|---|
[21-06-27 개인스터디] fp-ts: Ord (0) | 2021.06.27 |
[21-06-18 개인스터디] fp-ts Eq 알아보기 + combinators pattern, contramap (0) | 2021.06.19 |
[21-06-15 사내모각코] Trait typescript로 구현해보기 (0) | 2021.06.16 |
[21-06-02 사내모각코] fp-ts: Option 알아보기 (0) | 2021.06.16 |