프로그래밍언어/JavaScript

[JavaScript] 함수형프로그래밍

문스코딩 2018. 7. 18. 23:52

 

01. 입출력에 대해

모든 함수는 두 종류의 입력과 출력을 가집니다.

  1. 일반적인 입출력을 가지는 함수
  1. 숨겨진 형태의 입출력을 가지는 함수 :: 입력과 출력은 없지만, 의존성을 가지며 작업을 하는 함수

숨겨진 형태의 입출력을 가지는 형태는 동작이 외부로 보이지 않습니다.

 

숨겨진 형태의 입출력을 가지는 함수

public void processNext() {
    Message message = InboxQueue.popMessage();      
    if (message != null) {         
    	process(message);     
    } 
}

 

InboxQueue는 분명히 이 함수의 입력입니다. 단, 그것이 명확하지 않다는 것 뿐입니다.
InboxQueue의 상태를 고려하지 않고는 다음 함수를 말할 수 없습니다.

 

 

이 숨겨진 입력과 출력은 공식적인 이름을 가지고 있습니다.
바로 부작용(부산물 :: side-effect)입니다.

우리가 이 함수를 호출하려면 인수 목록에는 없지만 필요한 것들이 무엇이고,
반환 값에 반영되지 않으면서 하는 일은 무엇인가를 알아야 합니다.

 

1.1 부작용(부산물)은 복잡성의 빙산

함수가 부작용(과 부원인)을 가진다면, 함수의 내부를 보지 않고 무엇을 필요로 하는지 무슨 일을 하는지 전혀 알 길이 없습니다.
부작용은 복잡성의 빙산입니다. API의 표면 아래에는 잠재적으로 엄청나게 큰 복잡성이 숨어 있습니다.
그래서 함수를 제대로 파악하려고 할 때, 가능한 대안은 세가지입니다.

  • 함수 정의를 파고 들거나
  • 복잡성을 표면위로 들어 내거나
  • 그냥 무시하고 잘되길 바라는 것입니다.

 

1.2 그래서 캡슐화를 하는가 ?

캡슐화는 구현 세부 사항을 숨기는 것에 관한 것입니다.
코드의 내부를 숨겨 호출하는 쪽으로 걱정할 필요가 없게 하는 것입니다.

 

1.3 부작용이 나쁜가?

부작용은 여러 원인에 의해서 달라질 수 있습니다.
그렇기 때문에 부작용이 있는 함수를 맹신할 수 없습니다.
부작용은 박스를 열고 그 안에 무엇이 들어 있는지 확인하지 않고서 입력과 출력을 결정할 수 없기 떄문입니다.

그것은 디버깅시에 큰 문제가 될수 있습니다.
함수가 부작용이 없는 함수라면, 몇가지 입력에 대해 출력을 확인하여 올바른지 여부를 알 수 있습니다.
하지만 부작용이 있는 함수라면? 어디까지가 디버깅의 범위가 되는지 알 수 없습니다.

 

1.4 우리는 항상 부작용을 표면으로 드러내야 한다.

우리가 복잡성에 대해 할 수 있는 일은 무엇일까?
사실 함수가 어떤 입력을 가진다면 그렇게 말하면 (표현하면) 됩니다.
출력으로 뭔가를 반환하면 그렇게 선언하면 됩니다.

부작용이 없어야 한다는 것은, 프로그래머가 바꾸고자하는 변수 외에는 바뀌어서는 안된다는 뜻입니다.
원본 데이터는 불변해야함을 기억해야합니다.
힘수형 프로그래밍에서는 프로그래머가 모든 것을 예층하고 통제할 수 있어야 합니다.

 

1.5 대표적 함수형 프로그래밍 함수 :: map, filter, reduce

 

var arr = [1,2,3,4,5]; 
var map = arr.map(function(x) { return x * 2; }) // [2, 4, 6, 8, 10]

 

처음에는 배열 (arr)를 넣어서 결과 (map)을 얻었습니다.
arr는 사용은 됬지만 값은 변하지 않았고, map이라는 결과를 내고 아무런 부작용도 낳지 않았습니다.
이것이 바로 순수함수입니다.

 

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

다음은 순수함수가 아닙니다. 바로 condition 변수 때문입니다. 이를 순수함수로 바꿔 봅시다.

 

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

다음처럼 하면 에러를 쉽게 추적할 수 있습니다.

 

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

 

코드는 조금 복잡해졌으나, 재사용성이 높아짐

 

var arr = [1,2,3,4,5,6,7,8,9,10]; 
arr.reduce(function(prev, cur) { return prev + cur; }); // 55

 

02. 순수함수란 ?

모든 입력이 입력으로 선언되고, 숨겨진 것이 없으며
마찬가지로 모든 출력이 출력으로 선언된 것을 순수 함수라고 합니다.
가장 대표적으로 getter & setter가 있습니다.

반대로 숨겨진 입출력이 있는 것은 순수하지 않은 것이며,
함수가 제공한다고 보이는 것은 사실 전체 절반만을 이야기 해 줄 뿐입니다.

 

03. 일급함수란 ?

함수를 값으로 다루는 것을 말합니다.

 

04. 함수형 프로그래밍이란 무엇인가요 ?

함수형 프로그래밍은 성공적인 프로그래밍을 위해 부수효과를 제거하고 조합성을 강조하는 프로그래밍 패러다임입니다.

 

부수 효과를 제거한다 >> 순수함수를 만든다.     
조합성을 강조한다 >> 모듈화 수준을 높인다.     
순수 함수 >> 오류를 줄이고 안정성을 높인다.     
모듈화 수준이 높다. >> 생산성을 높인다.

함수형 프로그래밍이란 순수 함수를 작성하는 것, 그러니까 숨겨진 입력이나 출력을 최대한 제거하여
가능한 우리 코드의 대부분이 단지 입력과 출력의 관계를 기술하게 끔 하는 것을 말합니다.

부작용을 완전히 피할 수는 없습니다.
대부분의 프로그램은 반환 값을 얻기 위해서가 아니라 어떤 동작을 하기 위해 실행하기 떄문입니다.
하지만 우리는 가능한 모든 곳에서 부작용을 제거하고, 또 제거할 수 없는 경우에는 철저하게 통제합니다.

 

05. 함수형 프로그래밍 언어란 무엇인가요 ?

모든 언어는 순수함수를 지원합니다.
필요한 일은 모든 입력 및 출력을 함수 signature에 올리는 것 뿐입니다.
함수형 프로그래밍 언어는 부작용 없는 프로그래밍을 지원하고 장려하는 언어입니다.

 

반응형