프로그래밍

[함수형 프로그래밍] 일급 함수 (First-class function)

Folivora 2020. 1. 13. 07:34

First-class citizen 정의

다음 특성을 가지는 녀석들을 일등 시민(...)이라 한다. 

  • 함수의 인자로 사용될 수 있다.
  • 함수의 결괏값으로 사용될 수 있다.
  • 변수에 대입(<=)할 수 있다.
  • 동등(혹은 동치; equality)을 정의할 수 있다.

함수가 first-class citizen 정의를 만족하면 First-class function이라 한다.

예제:  미분값 구하기

내가 자주 드는 예제는 미분 값을 계산하는 함수를 만들 수 있는가이다.

\[ f'(x) = \lim_{h \to 0} \frac{f(x+h)-f(x)}{h} \]

 

C++ 코드

#include <iostream>
#include <functional>

double f(double x) { return 3 * x * x; }

double derivative(double (*func)(double), double x)
{
    const double delta = 0.001;
    return (f(x + delta) - f(x)) / delta;
}

typedef std::function<double(double)> Function;

Function d(const Function &f)
{
    const double delta = 0.001;
    return [f, delta](double x) { return (f(x + delta) - f(x)) / delta; };
}

int main()
{
    std::cout << "== using a function pointer ==" << std::endl;
    std::cout << "f'(2) = " << derivative(f, 2) << std::endl;

    std::cout << "== std::function ==" << std::endl;
    std::cout << "f'(2) = " << d(f)(2) << std::endl;
    std::cout << "f''(2) = " << d(d(f))(2) << std::endl;
    std::cout << "f'''(2) = " << d(d(d(f)))(2) << std::endl;

    return 0;
}

 

실행 결과

== using a function pointer ==
f'(2) = 12.003
== std::function ==
f'(2) = 12.003
f''(2) = 6
f'''(2) = 3.55271e-06

 

함수 포인터(Function pointer)로 어떻게 구현은 할 수 있었지만, derivative(f, 2)를 재사용하는 것은 불가능하다. 일계 도함수 "값"은 구할 수 있어도 일계 도함수 자체는 정의할 수 없다. 때문에 이계도함수는 구할 수 없는 것이다. 반면에 std::function<> 객체에 대입시키고, 도함수의 정의대로 함수를 리턴한다면? 값을 리턴한 것이 아니라 함수 자체를 리턴했으므로 고계 도함수를 구하는 것도 전혀 문제없다. C++에서는 문법이 다소 복잡하지만 언어 설계 당시에 first-class function으로 놓고 설계한 언어들은 훨씬 더 간결한 코드로 구현 가능하다. :)