고차 함수의 세 가지 기능

 

고차 함수 : 하나 이상의 함수를 인수로 사용할 수 있으며 반환 값으로 함수 사용이 가능한 함수

 

일급 함수와 고차 함수의 개념은 매우 유사하지만 일급 함수는 언어적 특성이고 고차 함수는 개별 함수의 특성이라는 차이가 있다.

"C++는 일급 함수를 지원한다" → 언어가 범위. 언어 차원에서 일급 함수를 지원하는지 여부를 따진다.

"xyz() 함수는 고차 함수다" → 함수가 범위. xyz() 함수가 고차 함수인지 여부를 따진다.

 

고차 함수의 특성, 맵 알아보기

std::map이 아니라 고차 함수 특징으로의 맵을 말한다.

어떤 컨테이너의 각 요소에 함수를 적용하여 동일한 순서의 새로운 컨테이너를 만드는 것이다.

 

std::vector<int> v1 = { 1, 2, 3, 4, 5 };
std::vector<int> v2;
v2.resize(v1.size());

/* v1을 사용해 새로운 컨테이너 v2를 만들어낸다 */
std::transform(std::begin(v1), std::end(v1), std::begin(v2),
    [](int i) { return i * i; });

std::cout << "v1 contains:";
for (auto v : v1) std::cout << " " << v;
std::cout << '\n';

std::cout << "v2 contains:";
for (auto v : v2) std::cout << " " << v;
std::cout << '\n';

 

함수가 인자로 넘겨졌으며 넘겨진 함수에 의해 동일한 작업이 수행되어 새로운 컨테이너가 생성되었기 때문에 std::transform은 맵이다.

 

 

고차 함수의 특성, 필터로 데이터 추출하기

기존 데이터 구조에 bool 값을 반환하는 조건을 적용하고 일치하는 요소들만 추려내어 새 데이터 구조를 만드는 것이다.

 

std::vector<int> numbers = { 0, 1, .., 19 };
std::vector<int> primes;

/* numbers에서 소수만 필터링하여 primes에 추가한다 */
std::copy_if(std::begin(numbers), std::end(numbers), std::back_inserter(primes),
    [](int n) {
        if (n < 2) {
            return (n != 0) ? true : false;
        }
        else {
            for (int j = 2; j < n; ++j) {
                if (n % j == 0) return false;
            }
        return true;
        }
    });

 

함수가 인자로 넘겨졌으며 넘겨진 함수의 반환된 bool값에 의해 새로운 컨테이너가 생성되었기 때문에 std::copy_if는 필터이다.

 

 

고차 함수의 특성, 폴드 알아보기

 

데이터 구조를 하나의 값으로 줄이는 기술을 말한다.

폴드는 왼쪽부터 결합하는 왼쪽 폴드와 오른쪽부터 결합하는 오른쪽 폴드 두 가지 타입이 있다.

 

((((0 + 1) + 2) + 3) + 4) // 왼쪽 폴드 foldl
(0 + (1 + (2 + (3 + 4)))) // 오른쪽 폴드 foldr

 

int addition(const int& x, const int& y)
{
    std::cout << x << " + " << y << '\n';
    return x + y;
}

std::vector<int> numbers = { 0, 1, 2, 3, 4 };

std::cout << "foldl" << '\n';
auto foldl = std::accumulate(std::begin(numbers), std::end(numbers), 0, addition); // 10
std::cout << '\n' << "foldr" << '\n';
auto foldr = std::accumulate(std::rbegin(numbers), std::rend(numbers), 0, addition); // 10

 

 

순방향 이터레이터를 사용하면 foldl, 역방향 이터레이터를 사용하면 foldr이 되고 컨테이너의 요소들이 누적합으로 계산되어 하나의 값으로 줄어들었기 때문에 std::accumulate는 폴드이다.

 

 

어떤 컨테이너의 각 요소에 동일한 함수를 적용했을 때,

◾ 맵 : 동일한 순서의 새로운 컨테이너를 만든다.

◾ 필터 : 조건에 일치하는 요소들만 추려내어 새로운 컨테이너를 만든다.

◾ 폴드 : 하나의 값으로 줄인다.

+ Recent posts