[Computer Science] Functional Programming


요약

Functional programming is a programming paradigm where programs are constructed by applying and composing functions.

함수형 프로그래밍이란

부수 효과(side effect)를 없애고 순수 함수(pure function)를 만들어 모듈화 수준을 높이는 프로그래밍 패러다임입니다.

함수형 프로그래밍의 특징

  • 부수 효과가 없습니다.
  • 순수 함수를 지향합니다.
  • 함수 외부 데이터에 의존하지 않습니다.
  • 함수 외부 데이터를 변경하지 않습니다.

부수 효과란

함수로 들어온 인자의 상태가 변경되거나 함수 외부의 상태가 변경되는 효과입니다.

순수 함수란

부수 효과가 없는 함수입니다. 즉, 동일한 인자를 주었을 때 항상 동일한 값을 반환하는 함수입니다.

순수 함수의 특징

  • 작성한 함수가 반드시 하나 이상의 인자를 받아야 합니다.
  • 반환값이 반드시 존재해야 합니다.
  • 함수 내에서 인자를 제외한 다른 변수를 사용하면 안 됩니다.
  • 동일 입력에 대한 동일 출력이 보장되어야 합니다.
  • 평가 시점이 중요하지 않아야 합니다.

함수형 프로그래밍의 예시

Wrong Example 1

const arr = [1, 2, 3, 4, 5];
const condition = function(x) {return x % 2 === 0}
const ex = function(array) {
    return array.filter(condition);
};
ex(arr); // [2, 4]

ex 함수가 인자로 받지 않은 condition 변수를 사용하고 있습니다.

Correct Example 1

const ex = function(array, cond) {
	return array.filter(cond);
};
ex(arr, condition);

condition 변수를 인자로 받는 순수 함수가 되었습니다. 이를 통해 에러 추적이 한결 쉬웠졌습니다.

Wrong Example 2

let sum = 0;
for (let i = 1; i <= 10; i++) {
  sum += i;
}

순수함수를 만들 때엔 반복문을 쓰지 않는게 좋습니다.

Correct Example 2-1

function add(sum, count) {
    sum += count;
    if (count > 0) {
        return add(sum, count - 1);
    } else {
        return sum;
    }
}
add(0, 10); // 55

인자로 받은 sum과 count만 활용했기 때문에 순수함수입니다.

Correct Example 2-2

const arr = [1,2,3,4,5,6,7,8,9,10];
const answer = arr.reduce((pre, cur) => {
	return pre + cur;
});	
console.log(answer); // 55

위 코드를 고차 함수인 reduce를 활용해서 간결하게 만들었습니다.

Wrong Example 3

let a = 0;

function increment() {
    return a += 1;
}

increment 함수가 외부 데이터 변수인 a에 의존하고 있습니다.

Correct Example 3

increment(a) {
	return a + 1;
}

인자로 받은 a와 상수 1만 활용했기 때문에 순수 함수입니다.

JS Collection Interface

아래의 함수들은 함수형 프로그래밍의 개념에 따라 기존 변수에 대한 부수 효과가 없도록 구현되었습니다.

map

const arr = ['foo', 'hello', 'diamond', 'A'];
const arr2 = arr.map((v) => v.length);
console.log(arr2) // [3, 5, 6, 1]

filter

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

reduce

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