JavaScript/함수형 프로그래밍과 JavaScript ES6+

함수형 자바스크립트 기본기(평가와 일급, 일급 함수, 고차 함수)

느리지만 꾸준하게 2021. 8. 17. 14:36

평가와 일급

평가란 코드가 계산되어 값을 만드는 것을 말한다.

즉 코드가 계산되어지는 것을 말한다. 아래 코드와 같이 코드가 각각 계산되어져서 만들어 졌다.

(1+2)+4
7

3+4
7

[1, 2]
(2) [1, 2]0: 11: 2length: 2[[Prototype]]: Array(0)

[1, 5]
(2) [1, 5]

[1, 2 + 3]
(2) [1, 5]0: 11: 5length: 2[[Prototype]]: Array(0)

[1, 2, [3, 4]]
(3) [1, 2, Array(2)]0: 11: 22: (2) [3, 4]length: 3[[Prototype]]: Array(0)

[1, 2, ...[3, 4]]
(4) [1, 2, 3, 4]

 

그리고 일급은 값으로 다룰 수 있다는 것이고 변수에 담을 수 있다는 것이다.

그리고 함수의 인자로 사용될 수 있고, 함수의 결과로 사용될 수 있다.

 

아래코드를 보면 10이라는 값을 a변수에 할당하고 add10이라는 함수가 있으면 add10의 인자로 a가 전달될 수 있다.

함수의 결과는(add10(a)) 함수의 리턴값으로 사용될 수 있다.

<script>
    const a = 10;
    const add10 = a => a + 10;
    const r = add10(a);
    log(r);
</script>

=> 20

즉 일급특성인 값으로 다룰 수 있고(10) 변수에 담을 수 있고(const a = 10) 함수의 인자로 사용되어지고(const add10 = a) 함수의 결과(const add10 = a => a +10;)로 사용 될 수 있다는 것이다.

 

일급 함수

자바스크립트에서 함수는 일급이다. 함수가 일급이라는 것은 함수를 값으로 다룰 수 있다는 것이다. 함수를 값으로 다룰 수 있다는 것은 변수에 함수를 값으로 다뤄서 담을 수 있다는 것이다.

아래와 같이 값으로 다뤄서 함수에게 전달하면 출력을 할 수 있고 함수의 인자로 함수가 사용될 수 있다.

또 함수를 평가로 만들어서 값을 다른 함수에게 전달할 수 있다. 

<script>
    const add5 = a => a + 5;
    log(add5);
    log(add5(5));
</script>

=>

a => a + 5
10

f1이라는 함수가 있으면 실행되었을 때 다시 함수를 리턴할 수 있다. f1을 실행한 결과를 전달하면 함수가 출력이 되고 f1함수의 결과는 함수인 것이다.

 

다시 f2라는 다른 변수에 담아서 마찬가지로 f2를 출력하면 () => 1이 출력된다.

그렇게 당겨진 함수를 원하는 시점에 평가해서(log(f2()) 원하는 값을 출력할 수 있다. 

    const f1 = () => () => 1;
    log(f1());

    const f2 = f1();
    log(f2);
    log(f2());
    
    =>
    
() => 1
() => 1
1

결론적으로 자바스크립트에서 함수가 일급이라는 것은 조합성과 추상화의 도구로 함수를 잘 사용할 수 있다는 이야기이다. 함수형 프로그래밍에서는 함수가 일급이라는 성질을 이용해 많은 조합성을 만들고 추상화의 좋은 도구로 사용할 수 있다.

 

고차 함수

위에서 일급함수는 함수가 값으로 다뤄질 수 있다는 것이였다.

고차 함수는 이러한 사실을 이용해서 함수를 값으로 다루는 함수를 고차함수라고 말한다.

 

고차 함수는 크게 두가지가 있는데 한번 다뤄보자.

  • 함수를 인자로 받아서 실행해주는 함수
  • 함수를 만들어 리턴하는 함수

 

먼저 함수를 인자로 받아서 실행해주는 함수를 보면 함수가 함수를 받아서 실행하고 있기 때문에

즉, 함수를 인자값으로 다루고 있기 때문에 고차함수라고 할 수 있다. apply1이라는 함수를 a라는 인자를 받아서 2를 더

하는 add2라는 함수가 있으면 apply1(add2)즉 apply1에 add2를 전달해서 log를 찍어서 확인하면 3이 출력된다.

 

정리하면 apply1이라는 함수는 add2 함수를 받아서 add2함수를 안에서 실행해주고 있다.

(const apply1 = f => (a => a + 2)(1);

a => a - 1이라는 다른 함수를 넣을 수 도 있다. 

 

다른 함수인 times라는 함수를 만들고 함수와 숫자를 받아서 숫자만큼 함수를 실행하는 것이다.

실행된 번째도 함수에게 전달되게 한다. 즉 times라는 함수는 함수를 값으로 받고 다른 값을 받아서 안에서 함수를 인자로 받아서 실행하면서 자기가 원하는 어떤 인자를 적용하는 함수이다.(applicative programming)

// applicative programming
<script>
    const apply1 = f => f(1);
    // const apply1 = f => (a => a + 2)(1); 
    const add2 = a => a + 2;
    
    log(apply1(add2));
    log(apply1(a => a - 1));
=>
3
0

//-------------------------------------------
    const times = (f, n) => {
        let i = -1;
        while (++i < n) f(i);
    };

    times(log, 3);

    times(a => log(a + 10), 3);
</script>
=>
0
1
2

10
11
12

함수를 만들어서 리턴하는 함수를 보면

addMaker라는 함수를 만들어서 a와 b를 더한다고 하고 add10이라는 변수에 할당해서 다른 함수를 만들어보자.

 

즉 addMaker는 함수를 리턴하는 함수 클로저를 리턴하는 함수이다. 클로저는 a+b함수가 a=>b=>a+b에서 a를 계속 기억하고 있다는 것이다. 함수이자 a를 계속 기억하는 클로저이다.

 

함수가 만들어 질 때 환경인 a와 함수 자체의 객체(b => a+b);를 함께 통칭해서 말하는 용어이다.

결론적으로 addMaker는 클로저를 리턴하는 함수이고 함수가 함수를 만들 때는 클로저를 리턴하기 위해서 사용한다.

 

두 가지 유형의 고차함수(함수를 인자로 받아서 실행하는 함수, 함수를 만들어 리턴하는 함수)를 알아보았다.

 

<script>
    const addMaker = a => b => a + b;
    const add10 = addMaker(10);
    log(add10(5));
    log(add10(10));
</script>

=>

15
20

 

 

 

 

<출처 : 유인동 함수형 프로그래밍과 JavaScript ES6+>

https://www.inflearn.com/course/functional-es6/dashboard

 

함수형 프로그래밍과 JavaScript ES6+ - 인프런 | 강의

ES6+와 함수형 프로그래밍을 배울 수 있는 강의입니다. 이 강좌에서는 ES6+의 이터러블/이터레이터/제너레이터 프로토콜을 상세히 다루고 응용합니다. 이터러블을 기반으로한 함수형 프로그래밍,

www.inflearn.com