함수형 프로그래밍

JavaScript 함수형 프로그래밍

함수를 일급 시민으로 취급하고, 부수 효과를 피하며, 불변 데이터를 다루는 프로그래밍 패러다임.


핵심 개념

일급 시민 (First-class Citizen)

함수를 다음처럼 다룰 수 있다:

순수 함수 (Pure Function)

불변성 (Immutability)

클로저 (Closure)

// JS 클로저 — 캡처한 변수를 참조
const fizz = (index) => (index % 3 === 0) ? "fizz" : "";
const buzz = (index) => (index % 5 === 0) ? "buzz" : "";

고차함수 (Higher-Order Functions)

map

각 요소를 변환하여 새로운 배열 생성. 원본 불변.

var arr = ['foo', 'hello', 'diamond', 'A'];
var arr2 = arr.map((v) => v.length);
// [3, 5, 7, 1]

filter

조건을 만족하는 요소들만 모아 새로운 배열 생성.

var arr = [4, 15, 377, 395, 400, 1024, 3000];
var arr2 = arr.filter((v) => (v % 5 === 0));
// [15, 395, 400, 3000]

reduce

배열 요소를 순회하며 하나의 결과값 생성.

let arr = [9, 2, 8, 5, 7];
let sum = arr.reduce((pre, val) => pre + val);
// 31

// map을 reduce로 구현
var arr2 = arr.reduce((pre, value) => {
    pre.push(value.length);
    return pre;
}, []);

reducemapfilter 모두 구현 가능 — 가장 범용적인 고차함수.


FizzBuzz로 보는 함수형 진화

// 1. 절차적
function fizzbuzz1() {
    for (let index = 1; index <= 100; index++) {
        const isFizz = index % 3 === 0;
        const isBuzz = index % 5 === 0;
        // switch ...
    }
}

// 2. 클로저 활용 — 각 판단 로직을 함수로 분리
function fizzclosure() {
    const fizz = (index) => (index % 3 === 0) ? "fizz" : "";
    const buzz = (index) => (index % 5 === 0) ? "buzz" : "";
    Array(100).fill().map((x, i) => i + 1).forEach(index => {
        let result = fizz(index) + buzz(index);
        console.log(result.length == 0 ? `${index}` : result);
    });
}

// 3. 선언적 — 모든 로직을 클로저 변수로
function fizzDeclarative() {
    const fizz = (index) => (index % 3 === 0) ? "fizz" : "";
    const buzz = (index) => (index % 5 === 0) ? "buzz" : "";
    const fizzbuzz = (index) => {
        let result = fizz(index) + buzz(index);
        return result.length == 0 ? `${index}` : result;
    };
    Array(100).fill().map((x, i) => i + 1).map(fizzbuzz).forEach(console.log);
}

불변성 라이브러리


참고