함수형 프로그래밍은 선언형 프로그래밍과 깊은 관련이 있습니다. 배열은 선언형 프로그래밍을 구현할 때 절대적으로 필요한 문법 기능입니다. 선언형은 명령형 방식 위에서 동작하는 인간에게 좀 더 친화적인 고수준 구현 방식입니다.
명령형 프로그래밍이란 프로그램의 기본 형태는 입력 데이터를 얻고 가공한 다음, 결과를 출력하는 형태로 구성됩니다.
for( ; ; ) {
// 입력 데이터 얻기
// 입력 데이터 가공해 출력 데이터 생성
// 출력 데이터 출력
반면에 선언형 프로그래밍은 시스템 자원의 효율적인 운용보다는 일괄된 문제 해결 구조에 더 집중합니다. 선언형 프로그래밍은 명령형 프로그래밍처럼 for 문을 사용하지 않고 모든 데이터를 배열에 담습니다. 그리고 문제가 해결될 때까지 끊임없이 또 다른 형태의 배열로 가공하는 방식으로 구현합니다.
1에서 100까지 더하기
export const range = (from: number, to: number): number[] =>
from < to ? [from, ...range(from + 1, to)] : []
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
}
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까지 홀수의 합 구하기
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
}
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'처럼 입력과 출력 변수의 타입이 서로 다를 수 있음을 고려해야 합니다.
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
}
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);