Jieunny의 λΈ”λ‘œκ·Έ

[TS] ν•¨μˆ˜ μ‘°ν•©μ˜ 원리와 μ‘μš© λ³Έλ¬Έ

Study/TypeScript

[TS] ν•¨μˆ˜ μ‘°ν•©μ˜ 원리와 μ‘μš©

Jieunny 2023. 2. 9. 14:45

πŸ“£  ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ΄λž€?

βœ”οΈ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° : 순수 ν•¨μˆ˜μ™€ μ„ μ–Έν˜• ν”„λ‘œκ·Έλž˜λ°μ˜ ν† λŒ€ μœ„μ— 'ν•¨μˆ˜ μ‘°ν•©' κ³Ό 'λͺ¨λ‚˜λ“œ μ‘°ν•©'으둜 μ½”λ“œλ₯Ό μ„€κ³„ν•˜κ³  κ΅¬ν˜„ν•˜λŠ” 기법

➰ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄λŠ” 정적 νƒ€μž…, νƒ€μž… μΆ”λ‘  등에 κΈ°λ°˜μ„ λ‘” κ³ μ°¨ νƒ€μž…, νŒ¨ν„΄ 맀친 λ“±μ˜ κ³ κΈ‰ κΈ°λŠ₯을 μ œκ³΅ν•œλ‹€.


πŸ“£  μ œλ„€λ¦­ ν•¨μˆ˜

βœ”οΈ number 와 같은 νƒ€μž…μ„ νƒ€μž… λ³€μˆ˜ T둜 ν‘œκΈ°ν•  λ•Œ 이λ₯Ό 'μ œλ„€λ¦­ νƒ€μž…' 이라고 ν•œλ‹€.

➰ ν•¨μˆ˜ 쑰합을 κ΅¬ν˜„ν•  λ•ŒλŠ” μ œλ„€λ¦­ ν•¨μˆ˜ ꡬ문을 μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

 

πŸ“ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ˜ μ œλ„€λ¦­ ν•¨μˆ˜ ꡬ문

function g1<T>(a: T): void {}

➰ μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ •μ˜ν•˜λ©΄ μ–΄λ–€ νƒ€μž…μ—λ„ λŒ€μ‘ν•  수 μžˆλ‹€.

➰ g1 ν•¨μˆ˜λŠ” a λ§€κ°œλ³€μˆ˜κ°€ μ œλ„€λ¦­ νƒ€μž…μœΌλ‘œ μ§€μ •λ˜μ—ˆλ‹€.

 

type Type1Func<T> = (T) => void
type Type2Func<T, Q> = (T, Q) => void
type Type3Func<T, Q, R> = (T, Q) => R
// Type3Func ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜λŠ” T와 Qνƒ€μž… 값을 μž…λ ₯λ°›μ•„ R νƒ€μž… 값을 λ°˜ν™˜ν•˜λŠ” 것을 μ˜λ―Έν•œλ‹€.

➰ νƒ€μž… 별칭에 μ œλ„€λ¦­ νƒ€μž…μ„ μ μš©ν•  수 μžˆλ‹€.

 

πŸ“ ν•¨μˆ˜μ˜ μ—­ν• 

➰ ν•¨μˆ˜ fκ°€ T νƒ€μž…μ˜ xκ°’μœΌλ‘œ R νƒ€μž…μ˜ y값을 λ§Œλ“ λ‹€.

(x: T) ~-> f -> (y: R)

➰ 이런 관계λ₯Ό μΌλŒ€μΌ 관계라고 ν•˜κ³ , 이런 λ™μž‘μ„ ν•˜λŠ” ν•¨μˆ˜λ₯Ό '맡(map)'이라고 ν‘œν˜„ν•œλ‹€.

 

type MapFunc<T, R> = (T) => R

➰ νƒ€μž… T인 값을 μ΄μš©ν•΄ νƒ€μž… R인 값을 λ§Œλ“€μ–΄μ£ΌλŠ” ν•¨μˆ˜μ˜ μ‹œκ·Έλ‹ˆμ²˜

 

πŸ“ 아이덴티티 ν•¨μˆ˜

➰ 맡 ν•¨μˆ˜μ˜ κ°€μž₯ λ‹¨μˆœν•œ ν˜•νƒœλŠ” μž…λ ₯κ°’ xλ₯Ό 가곡 없이 κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•˜λŠ” 것이닀.

➰ μ΄λŸ¬ν•œ 역할을 ν•˜λŠ” ν•¨μˆ˜μ˜ μ΄λ¦„μ—λŠ” 보톡 identity λ˜λŠ” IλΌλŠ” 단어가 ν¬ν•¨λœλ‹€.

type MapFunc<T, R> = (T) => R
type IdentityFunc<T> = MapFunc<T, T>

 

const numberIdentity: IdentityFunc<number> = (x: number): number => x
const stringIdentity: IdentityFunc<string> = (x: string): string => x

➰ μ •μ˜ν•œ μ œλ„€λ¦­ ν•¨μˆ˜ IdentityFunc<T>λŠ” λ‹€μ–‘ν•œ ν•¨μˆ˜λ₯Ό μ„ μ–Έν•  λ•Œ μ‚¬μš©ν•  수 μžˆλ‹€.


πŸ“£  κ³ μ°¨ ν•¨μˆ˜μ™€ 컀리

βœ”οΈ ν•¨μˆ˜μ—μ„œ λ§€κ°œλ³€μˆ˜μ˜ 개수λ₯Ό 애리티(arity) 라고 ν•œλ‹€.

➰ 각 ν•¨μˆ˜μ˜ 애리티가 κ°™λ‹€λ©΄ μ—°κ²°ν•΄μ„œ μ‚¬μš©ν•  수 μžˆλ‹€.

y = h(g(f(x)))

➰ ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œλŠ” compose λ‚˜ pipe ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ ν•¨μˆ˜λ“€μ„ μ‘°ν•©ν•΄ μƒˆλ‘œμš΄ ν•¨μˆ˜λ₯Ό λ§Œλ“€ 수 μžˆλ‹€.

 

πŸ“ κ³ μ°¨ ν•¨μˆ˜λž€?

➰ νƒ€μž…μŠ€ν¬λ¦½νŠΈμ—μ„œ ν•¨μˆ˜λŠ” λ³€μˆ˜μ— λ‹΄κΈ΄ ν•¨μˆ˜ ν‘œν˜„μ‹μ΄κ³  ν•¨μˆ˜ ν‘œν˜„μ‹μ΄λž€ μΌμ’…μ˜ 값이기 λ•Œλ¬Έμ— ν•¨μˆ˜μ˜ λ°˜ν™˜κ°’μœΌλ‘œ ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•  수 μžˆλ‹€.

➰ μ–΄λ–€ ν•¨μˆ˜κ°€ 또 λ‹€λ₯Έ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•  λ•Œ κ·Έ ν•¨μˆ˜λ₯Ό 'κ³ μ°¨ ν•¨μˆ˜' 라고 ν•œλ‹€.

➰ ν•¨μˆ˜κ°€ μ•„λ‹Œ λ‹¨μˆœν•œ 값을 λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜λŠ” '1μ°¨ ν•¨μˆ˜' 라고 ν•œλ‹€.

 1μ°¨ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λ©΄ '2μ°¨ κ³ μ°¨ ν•¨μˆ˜', 2μ°¨ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λ©΄ '3μ°¨ κ³ μ°¨ ν•¨μˆ˜' 라고 ν•œλ‹€.

type FirstOrderFunc<T, R> = (T) => R
// R νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•˜λŠ” 1μ°¨ ν•¨μˆ˜
type SecondOrderFunc<T, R> = (T) => FirstOrderFunc<T, R>
// 1μ°¨ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” 2μ°¨ κ³ μ°¨ν•¨μˆ˜
type ThirdOrderFunc<T, R> = (T) => SecondOrderFunc<T, R>
// 2μ°¨ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” 3μ°¨ κ³ μ°¨ν•¨μˆ˜

 

const inc: FirstOrderFunc<number, number> = (x: number): number => x + 1
inc(1) // 1μ°¨ ν•¨μˆ˜μ΄λ―€λ‘œ ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό ν•œ 번 μ‚¬μš©ν•œλ‹€.

➰ inc ν•¨μˆ˜λŠ” λ‹¨μˆœνžˆ number νƒ€μž…μ˜ 값을 λ°˜ν™˜ν•˜λ―€λ‘œ 1μ°¨ ν•¨μˆ˜μ΄λ‹€.

 

const add: SecondOrderFunc<number, number> =
    (x: number): FirstOrderFunc<number, number> =>
    (y: number): number => x + y
    
add(1)(2)
// 2μ°¨ κ³ μ°¨ ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•ŒλŠ” ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό 두 번 연속 μ‚¬μš©ν•œλ‹€.

➰ add ν•¨μˆ˜λŠ” FirstOrderfunc<number, number> ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ 2μ°¨ κ³ μ°¨ ν•¨μˆ˜μ΄λ‹€.

➰ ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό μ—°μ†μœΌλ‘œ μ‚¬μš©ν•˜λŠ” 것을 '컀리(curry)' 라고 ν•œλ‹€.

 

const add3: ThirdOrderFunc<number, number> =
    (x: number): SecondOrderFunc<number, number> =>
    (y: number): FirstOrderFunc<number, number> =>
    (z: number): number -> x + y + z
    
add3(1)(2)(3)
// 3μ°¨ κ³ μ°¨ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό μ„Έ 번 이어 λΆ™μ–΄ ν˜ΈμΆœν•œλ‹€.

➰ add3 ν•¨μˆ˜λŠ” FirstOrderFunc ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λŠ” SecondOrderFunc ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•˜λ―€λ‘œ 3μ°¨ κ³ μ°¨ ν•¨μˆ˜μ΄λ‹€.

 

πŸ“ λΆ€λΆ„ 적용 ν•¨μˆ˜μ™€ 컀리

➰ κ³ μ°¨ ν•¨μˆ˜λ“€μ€ μžμ‹ μ˜ 차수만큼 ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό 연달아 μ‚¬μš©ν•œλ‹€.

➰ μžμ‹ μ˜ μ°¨μˆ˜λ³΄λ‹€ ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό 적게 μ‚¬μš©ν•˜λ©΄ 'λΆ€λΆ„ 적용 ν•¨μˆ˜' λ˜λŠ” 'λΆ€λΆ„ ν•¨μˆ˜' 라고 ν•œλ‹€.

const add1: SecondOrderFunc<number, number> = add(1)
// add1은 λΆ€λΆ„ ν•¨μˆ˜μ΄λ‹€.

add1(2)
add(1)(2)
// add1은 add(1)κ³Ό λ˜‘κ°™λ‹€.

➰ add1은 1μ°¨ ν•¨μˆ˜μ΄λ―€λ‘œ ν•¨μˆ˜ 호좜 μ—°μ‚°μžλ₯Ό 1개 μ‚¬μš©ν•΄ 일반 ν•¨μˆ˜μ²˜λŸΌ ν˜ΈμΆœν•  수 μž‡λ‹€.

➰ add1(2)둜 ν˜ΈμΆœν•˜λ©΄ add(1)κ³Ό ν•¨κ»˜ μ „λ‹¬λ˜μ„œ 3이 좜λ ₯λœλ‹€.

 

πŸ“ ν΄λ‘œμ €

➰ κ³ μ°¨ ν•¨μˆ˜μ˜ λͺΈν†΅μ—μ„œ μ„ μ–Έλ˜λŠ” λ³€μˆ˜λ“€μ€ ν΄λ‘œμ €(closure)λΌλŠ” 유효 λ²”μœ„λ₯Ό 가진닀.

➰ ν΄λ‘œμ €λŠ” 'μ§€μ†λ˜λŠ” 유효 λ²”μœ„' λ₯Ό μ˜λ―Έν•œλ‹€.

function add(x: number): (number) => number {	// λ°”κΉ₯μͺ½ 유효 λ²”μœ„ μ‹œμž‘
    return function(y: number): number {	// μ•ˆμͺ½ 유효 λ²”μœ„ μ‹œμž‘
        return x + y	// ν΄λ‘œμ €
    }	// μ•ˆμͺ½ 유효 λ²”μœ„ 끝
}	// λ°”κΉ₯μͺ½ 유효 λ²”μœ„ 끝

➰ return x + y 뢀뢄은 add ν•¨μˆ˜κ°€ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μ˜ λ°˜ν™˜λ¬ΈμΈλ°, 이 ν•¨μˆ˜λŠ” μžμ‹ μ˜ λ°”κΉ₯μͺ½ 유효 λ²”μœ„μ— μžˆλŠ” λ³€μˆ˜ xλ₯Ό μ°Έμ‘°ν•˜κ³  μžˆλ‹€.

➰ addκ°€ λ°˜ν™˜ν•˜λŠ” ν•¨μˆ˜μ—μ„œ λ³Ό λ•Œ xλŠ” 이해할 수 μ—†λŠ” λ³€μˆ˜μ΄λ©°, 이처럼 λ²”μœ„ μ•ˆμ—μ„œλŠ” κ·Έ 의미λ₯Ό μ•Œ 수 μ—†λŠ” λ³€μˆ˜λ₯Ό '자유 λ³€μˆ˜' 라고 λΆ€λ₯Έλ‹€.

➰ νƒ€μž… μŠ€ν¬λ¦½νŠΈλŠ” 자유 λ³€μˆ˜κ°€ 있으면 κ·Έ λ³€μˆ˜μ˜ λ°”κΉ₯μͺ½ 유효 λ²”μœ„μ—μ„œ 자유 λ³€μˆ˜μ˜ 의미(μ„ μ–Έλ¬Έ)을 μ°ΎλŠ”λ‹€.

 

const add1 = add(1)	// λ³€μˆ˜ x λ©”λͺ¨λ¦¬ μœ μ§€

➰  add ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ”λΌλ„ λ³€μˆ˜ x의 λ©”λͺ¨λ¦¬κ°€ ν•΄μ œλ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— ν΄λ‘œμ €λ₯Ό μ§€μ†λ˜λŠ” 유효 λ²”μœ„λΌκ³  λΆ€λ₯΄λŠ” 것이닀.

const result = add1(2) // result에 3을 μ €μž₯ ν›„ λ³€μˆ˜ x λ©”λͺ¨λ¦¬ ν•΄μ œ

➰ 이처럼 κ³ μ°¨ ν•¨μˆ˜κ°€ λΆ€λΆ„ ν•¨μˆ˜κ°€ μ•„λ‹Œ 'κ°’'을 λ°œμƒν•΄μ•Ό λΉ„λ‘œμ†Œ 자유 λ³€μˆ˜μ˜ λ©”λͺ¨λ¦¬κ°€ ν•΄μ œλ˜λŠ” 유효 λ²”μœ„λ₯Ό 'ν΄λ‘œμ €'라고 ν•œλ‹€.

 

const MakeNames = (): () => string => {	// λ°”κΉ₯μͺ½ 유효 λ²”μœ„
    const names = ['Jack', 'Jane', 'Smith']
    let index = 0
    return (): string => {	// 인μͺ½ 유효 λ²”μœ„
        if(index == names.length)
            index = 0
        return names[index++]
    }
}

const makeName: () => string = makeNames()
console.log(
    [1, 2, 3, 4, 5, 6].map(n => makeName())
}

//['Jack', 'Jane', 'Smith', 'Jack', 'Jane', 'Smith']

➰ makeNames ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜λ©΄ () => string νƒ€μž…μ˜ ν•¨μˆ˜ makeName을 μ–»λŠ”λ‹€.

➰ 배열에 map ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•΄μ„œ 각 μš”μ†Œμ— makeName() ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λ©΄ λ°°μ—΄μ˜ μ•„μ΄ν…œ 수만큼 총 μ—¬μ„― 번 makename() ν•¨μˆ˜κ°€ ν˜ΈμΆœλœλ‹€.

➰ indexλŠ” names.length와 값이 같아지면 λ‹€μ‹œ 0이 λ˜λ―€λ‘œ makeName ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” ν•œ makeNames ν•¨μˆ˜μ— ν• λ‹Ήλœ ν΄λ‘œμ €λŠ” ν•΄μ œλ˜μ§€ μ•ŠλŠ”λ‹€.


πŸ“£  ν•¨μˆ˜ μ‘°ν•©

βœ”οΈ ν•¨μˆ˜ μ‘°ν•© : μž‘μ€ κΈ°λŠ₯을 κ΅¬ν˜„ν•œ ν•¨μˆ˜λ₯Ό μ—¬λŸ¬ 번 μ‘°ν•©ν•΄ 더 의미 μžˆλŠ” ν•¨μˆ˜λ₯Ό λ§Œλ“€μ–΄ λ‚΄λŠ” ν”„λ‘œκ·Έλž¨ 섀계 기법

➰ ν•¨μˆ˜ 쑰합을 ν•  수 μžˆλŠ” ν•¨μˆ˜ : compose, pipe

 

πŸ“ compose ν•¨μˆ˜

➰ κ°€λ³€ 인수 μŠ€νƒ€μΌλ‘œ ν•¨μˆ˜λ“€μ˜ 배열을 μž…λ ₯λ°›λŠ”λ‹€.

➰ ν•¨μˆ˜λ“€μ„ μ‘°ν•©ν•΄ λ§€κ°œλ³€μˆ˜ xλ₯Ό μž…λ ₯λ°›λŠ” 1μ°¨ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•œλ‹€.

const compose = <T, R>(...functions: readonly Function[]): Function => (x:T): (T) => R => {
    const deepCopiedFunctions = [...functions]
    return deepCopiedFunctions.reverse().reduce((value, func) => func(value), x)
}

 

const composedFGH = compose(h, g, f)
conposedFGH('x')
// h(g(f(x)))

➰ compose(h, g, f)둜 λ§Œλ“  composedFGHλŠ” 1μ°¨ ν•¨μˆ˜μ΄λ―€λ‘œ 일반 ν•¨μˆ˜μ²˜λŸΌ ν˜ΈμΆœν•  수 μžˆλ‹€.

 

const inc = x => x + 1
const composed = compose(inc, inc, inc)
composed(1)	// 4

➰ compose의 λ™μž‘μœΌλ‘œ 1 -> inc -> 2 -> inc -> 3 -> inc -> 4 의 과정이 λ°œμƒν–ˆλ‹€.

➰ 1을 가지고 inc ν•¨μˆ˜κ°€ μ„Έ 번 연달아 ν˜ΈμΆœλ˜λ©΄μ„œ 결괏값 4κ°€ λ‚˜μ˜¨λ‹€.

 

πŸ“ pipe ν•¨μˆ˜

➰ compose와 λ™μž‘ μ›λ¦¬λŠ” κ°™μ§€λ§Œ, μ‘°ν•©ν•˜λŠ” ν•¨μˆ˜λ“€μ˜ μˆœμ„œλ§Œ λ°˜λŒ€μ΄λ‹€.

const pipe = <T>(...functions: readonly Function[]): Function => (x:T): T => {
    return functions.reduce((value, func) => func(value), x)
}

 

const piped = pipe(f, g, h)
piped('x')
// h(g(f(x)))

➰ compose와 달리 λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬λœ ν•¨μˆ˜λ₯Ό λ’€μ—μ„œλΆ€ν„° μ μš©ν•œλ‹€.

 

πŸ“ pipe 와 compose ν•¨μˆ˜ 뢄석

➰ ν•¨μˆ˜λ“€μ˜ μ‹œκ·Έλ‹ˆμ²˜κ°€ 각각 λͺ¨λ‘ λ‹€λ₯΄λ©΄ κ°€λ³€ 인수 functions의 νƒ€μž…μ„ μ„€μ •ν•˜κΈ° μ–΄λ ΅λ‹€.

➰ λ•Œλ¬Έμ— functions은 μžλ°”μŠ€ν¬λ¦½νŠΈ νƒ€μž… Functionλ“€μ˜ 배열인 Function[]으둜 μ„€μ •ν•œλ‹€.

➰ pipe ν•¨μˆ˜λŠ” functions 배열을 μ‘°ν•©ν•΄ μ–΄λ–€ ν•¨μˆ˜λ₯Ό λ°˜ν™˜ν•΄μ•Ό ν•˜λ―€λ‘œ λ°˜ν™˜ νƒ€μž…μ€ Function으둜 μ„€μ •ν•œλ‹€.

➰ pipe ν•¨μˆ˜λ‘œ μ‘°ν•©λœ κ²°κ³Ό ν•¨μˆ˜μ˜ μ• λ¦¬ν‹°λŠ” 1이며, κ·Έ λ§€κ°œλ³€μˆ˜ x의 νƒ€μž…μ€ μ œλ„€λ¦­ νƒ€μž…μΈ T둜 μ„€μ •ν•œλ‹€.

➰ ν•¨μˆ˜ λͺΈν†΅μ€ reduce ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•΄μ„œ λ§€κ°œλ³€μˆ˜μΈ λ³€μˆ˜ xλ₯Ό μ΄ˆκΉƒκ°’μœΌλ‘œ λ‘”λ‹€.

➰ reduce λ©”μ„œλ“œμ˜ 콜백 ν•¨μˆ˜ 뢀뢄은 (value, func) ν˜•νƒœμ˜ λ§€κ°œλ³€μˆ˜ ꡬ쑰λ₯Ό κ°€μ Έμ•Ό ν•œλ‹€.

const pipe = (...functions: Function[]): Function =>(x: T) => T => {
    return functions.reduce((value, func) => func(value), x)
}

 

 

➰ compose ν•¨μˆ˜λŠ” pipe ν•¨μˆ˜μ™€ λ§€κ°œλ³€μˆ˜ λ°©ν–₯이 λ°˜λŒ€μ΄λ―€λ‘œ functions.reverse()λ₯Ό ν˜ΈμΆœν•˜λŠ” μ½”λ“œλ₯Ό μΆ”κ°€ν•΄μ£Όλ©΄ λœλ‹€.

➰ ν•˜μ§€λ§Œ composeλŠ” 순수 ν•¨μˆ˜μ˜ λͺ¨μŠ΅μœΌλ‘œ λ™μž‘ν•΄μ•Ό ν•˜λ―€λ‘œ functions을 μ „κ°œ μ—°μ‚°μžλ‘œ μ „κ°œν•΄μ„œ κΉŠμ€ 볡사λ₯Ό ν•΄μ€€λ‹€.

const compose = <T>(...functions: readnly Function[]): Function => (x:T) :T => {
    const deepCopiedFunctions = [...functions]
    deepCopiedFunctions.reverse().reduce((value, func) => func(value), x)
}

 

πŸ“ λΆ€λΆ„ ν•¨μˆ˜μ™€ ν•¨μˆ˜ μ‘°ν•©

➰ κ³ μ°¨ ν•¨μˆ˜μ˜ λΆ€λΆ„ ν•¨μˆ˜λŠ” ν•¨μˆ˜ 쑰합에 μ‚¬μš©λ  수 μžˆλ‹€.

const add = x = > y => x + y
const inc = add(1)

const add3 = pipe(
   inc,
   add(2)
}

console.log(
   add3(1)	//4
}

➰ inc ν•¨μˆ˜λŠ” add의 λΆ€λΆ„ ν•¨μˆ˜μ΄λ‹€.

➰ add3은 pipe ν•¨μˆ˜λ₯Ό 가지고 inc와 add(2)λ₯Ό μ‘°ν•©ν•΄μ„œ λ§Œλ“  ν•¨μˆ˜μ΄λ‹€.

➰ add3은 일반 ν•¨μˆ˜ μ΄λ―€λ‘œ add3(1)둜 ν˜ΈμΆœν•˜λ©΄, inc ν•¨μˆ˜κ°€ ν˜ΈμΆœλ˜μ–΄ κ°’ 1은 2κ°€ 되고, add(2)에 μ˜ν•΄ μ΅œμ’… 4λΌλŠ” 값이 λœλ‹€.

 

πŸ“ ν¬μΈνŠΈκ°€ μ—†λŠ” ν•¨μˆ˜

➰ ν•¨μˆ˜ 쑰합을 κ³ λ €ν•΄ μ„€κ³„ν•œ ν•¨μˆ˜λ₯Ό 'ν¬μΈνŠΈκ°€ μ—†λŠ” ν•¨μˆ˜' 라고 ν•œλ‹€.

const map = f => a => a.map(f)
// map ν•¨μˆ˜λŠ” fλΌλŠ” ν•¨μˆ˜λ₯Ό λ°›λŠ”λ°, fλΌλŠ” ν•¨μˆ˜λŠ” aλΌλŠ” λ§€κ°œλ³€μˆ˜λ₯Ό λ°›κ³ , κ·Έ λ§€κ°œλ³€μˆ˜μ— fλΌλŠ” ν•¨μˆ˜λ₯Ό μ μš©ν•œλ‹€.

➰ map(f) ν˜•νƒœμ˜ λΆ€λΆ„ ν•¨μˆ˜λ₯Ό λ§Œλ“€λ©΄ composeλ‚˜ pipe에 μ‚¬μš©ν•  수 μžˆλ‹€.

 

const square = value => value * value
const squaredMap = map(square)
// const squaredMap = a => map(square)(a)

➰ 주석 λΆ€λΆ„κ³ΌλŠ” 달리 ꡳ이 aλ₯Ό μ§€μ •ν•˜μ§€ μ•ŠλŠ” 것이 ν¬μΈνŠΈκ°€ μ—†λ‹€λŠ” 것이닀.

 

const fourSquare = pipe(
    squaredMap,
    squaredMap
)

console.log(
    fourSquare([3, 4]) // [82, 256] [(3*3)*(3*3), (4*4)*(4*4)]
)

'Study > TypeScript' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

[TS] Exercises 4  (0) 2023.07.19
[TS] Exercises 1~3  (0) 2023.07.18
[TS] Promise와 async/await ꡬ문  (0) 2023.02.06
[TS] λ°˜λ³΅κΈ°μ™€ 생성기  (0) 2023.02.03
[TS] λ°°μ—΄κ³Ό νŠœν”Œ  (2) 2023.02.02