[ TS ] 배열과 튜플(2)

유기훈·2022년 6월 27일
0
post-thumbnail

선언형 프로그래밍과 배열

함수형 프로그래밍은 선언형 프로그래밍과 깊은 관련이 있습니다. 배열은 선언형 프로그래밍을 구현할 때 절대적으로 필요한 문법 기능입니다. 선언형은 명령형 방식 위에서 동작하는 인간에게 좀 더 친화적인 고수준 구현 방식입니다.

명령형 프로그래밍

명령형 프로그래밍이란 프로그램의 기본 형태는 입력 데이터를 얻고 가공한 다음, 결과를 출력하는 형태로 구성됩니다.

for( ; ; ) {
// 입력 데이터 얻기
// 입력 데이터 가공해 출력 데이터 생성
// 출력 데이터 출력

반면에 선언형 프로그래밍은 시스템 자원의 효율적인 운용보다는 일괄된 문제 해결 구조에 더 집중합니다. 선언형 프로그래밍은 명령형 프로그래밍처럼 for 문을 사용하지 않고 모든 데이터를 배열에 담습니다. 그리고 문제가 해결될 때까지 끊임없이 또 다른 형태의 배열로 가공하는 방식으로 구현합니다.

  • 문제를 푸는 데 필요한 모든 데이터 배열에 저장
  • 입력 데이터 배열을 가공해 출력 데이터 배열 생성
  • 출력 데이터 배열에 담긴 아이템 출력

선언형 프로그래밍 예시

1에서 100까지 더하기

range.ts

export const range = (from: number, to: number): number[] =>
    from < to ? [from, ...range(from + 1, to)] : []

fold.ts

export const fold = <T>(array: T[], callback: (result: T, val: T) => T, initValue: T) => {
    let result: T = initValue
    for (let i = 0; i < array.length; i++) {
        const value: T = array[i]
        result = callback(result, value)
    }
    return result
}

declarative-sum.ts

import { range } from './range/range'
import { fold } from './range/fold'

let numbers: number[] = range(1, 100 + 1)
let result = fold(numbers, (result, value) => result + value, 0)
console.log(result); // 5050

1에서 100까지 홀수의 합 구하기

filter.ts

export const filter = <T>(array: T[], callback: (value: T, index?: number) => boolean): T[] => {
    let result: T[] = []
    for (let index: number = 0; index < array.length; ++index) {
        const value = array[index]
        if (callback(value, index))
            result = [...result, value]
    }
    return result
}

result.ts

import { range } from './range/range'
import { fold } from './range/fold'
import { filter } from './range/filter'

let numbers: number[] = range(1, 100 + 1)
const isOdd = (n: number): boolean => n % 2 != 0
let result = fold(filter(numbers, isOdd), (result, value) => result + value, 0)
console.log(result); // 2500

map: 배열 데이터 가공하기
수학에서map은 'x -> y'형태로 어떤 값을 또 다른 값으로 만들어 주는 연산을 의미합니다. 그런데 변수 x와 y의 타입까지 생각하면 map은 'x: T -> y: Q'처럼 입력과 출력 변수의 타입이 서로 다를 수 있음을 고려해야 합니다.

map.ts

export const map = <T, Q>(array: T[], callback: (value: T, index?: number) => Q): Q[] => {
    let result: Q[] = []
    for (let index = 0; index < array.length; ++index) {
        const value = array[index]
        result = [...result, callback(value, index)]
    }
    return result
}

result.ts

import { range } from './range/range'
import { fold } from './range/fold'
import { map } from './range/map'

let numbers: number[] = range(1, 100 + 1)
let result = fold(
    map(numbers, value => value * value),
    (result, value) => result + value, 0
)
console.log(result);
profile
개발할 수 있어 감사하다

0개의 댓글