C++의 재귀 Lambda 함수

Saad Aslam 2023년10월12일
  1. C++ 재귀 람다 함수
  2. std::function을 사용하는 C++ 재귀 Lambda 함수
  3. 일반 람다를 사용하는 C++ 재귀 람다 함수
  4. y_combinator를 사용하는 C++ 재귀 Lambda 함수
C++의 재귀 Lambda 함수

이 기사에서는 C++에서 사용할 수 있는 재귀 람다를 이해합니다.

C++ 재귀 람다 함수

재귀란 함수가 자신을 (직간접적으로) 호출하는 과정을 말하며, 이 과정에 해당하는 함수를 재귀 함수라고 합니다. 재귀 람다 식은 이 프로세스의 결과입니다.

재귀 방법을 사용하여 일부 문제에 접근하면 훨씬 쉽게 해결할 수 있습니다.

로컬 코드를 재구성하는 과정에서 람다는 유용한 도구입니다. 반면에 내부에서 람다를 활용하고 싶은 경우가 있습니다.

이는 두 가지 이유 중 하나로 수행될 수 있습니다: 직접 재귀를 활성화하거나 클로저가 연속으로 등록될 수 있도록 합니다. 현재 버전의 C++에서는 이 작업을 성공적으로 수행하기가 매우 어렵습니다.

C++에서 재귀 Lambda 함수 구현

첫 번째 단계에서는 필요한 라이브러리를 가져옵니다.

#include <functional>
#include <iostream>

main() 함수 내에서 int 유형의 변수를 초기화하고 정수 값을 할당합니다.

int main() { int anyNumber = 456789; }

그런 다음 void 유형의 함수를 생성하고 reverseByRecursiveLambda라는 이름을 지정합니다.

function<void()> reverseByRecursiveLambda;

이제 재귀 람다 함수로 reverseByRecursiveLambda 함수를 초기화합니다.

reverseByRecursiveLambda = [&]() {};

이 메서드 내에서 anyNumber의 정수 값이 0과 같으면 아무 것도 반환하지 않는다는 검사를 구현해야 합니다. 그렇지 않은 경우 함수는 다음 작업 집합으로 이동해야 합니다.

그런 다음 함수는 일련의 수학적 계산을 수행한 후 결과를 인쇄합니다. 마지막 단계로 reverseByRecursiveLambda()라는 함수를 다시 실행합니다.

if (anyNumber == 0) return;

cout << anyNumber % 10 << " ";
anyNumber /= 10;
reverseByRecursiveLambda();

이 함수가 실행을 완료한 후에는 main() 메서드 내에서 이 함수를 호출하기만 하면 됩니다.

int main() { reverseByRecursiveLambda(); }

완전한 소스 코드:

#include <functional>
#include <iostream>

using namespace std;

int main() {
  int anyNumber = 123456789;

  function<void()> reverseByRecursiveLambda;

  reverseByRecursiveLambda = [&]() {
    if (anyNumber == 0) return;

    cout << anyNumber % 10 << " ";
    anyNumber /= 10;
    reverseByRecursiveLambda();
  };

  reverseByRecursiveLambda();
}

출력:

9 8 7 6 5 4 3 2 1

std::function을 사용하는 C++ 재귀 Lambda 함수

std::function 클래스 템플릿은 다양한 용도로 사용할 수 있는 다형성 함수 래퍼입니다. 모든 람다 식 바인딩 식 또는 기타 함수 개체는 std::function 클래스의 인스턴스 내에서 저장, 복사 및 호출될 수 있습니다.

또한 이러한 인스턴스는 멤버 함수에 대한 포인터와 데이터 멤버에 대한 포인터를 보유할 수 있습니다.

다음 예제에서는 팩토리얼의 스냅샷을 찍어야 합니다. 그런 다음 람다 본문 내에서 참조할 수 있습니다.

예제 코드:

#include <functional>
#include <iostream>

int main() {
  const std::function<int(int)> factorial = [&factorial](int n) {
    return n > 1 ? n * factorial(n - 1) : 1;
  };

  std::cout << "The factorial of 5 is: " << factorial(5);
  return factorial(5);
}

출력:

The factorial of 5 is: 120

일반 람다를 사용하는 C++ 재귀 람다 함수

일반 람다 식은 auto 유형의 인수가 하나 이상 있는 람다 식을 나타냅니다.

이 옵션을 가능하게 한 일반 람다 표현식 덕분에 재귀 람다 함수를 만드는 데 std::function을 사용할 필요가 없습니다. 람다 식의 유형은 이름만으로 결정할 수 없습니다.

따라서 C++14가 출시되기 전에는 std::function 안에 재귀 람다 식을 포함해야 했습니다. std::function에 종속되지 않으며 숫자 기본 유형에서 제대로 수행하기 위해 데이터를 캡처할 필요가 없습니다.

예제에서는 일반 람다 auto를 사용하여 map에 저장된 데이터를 표시하는 방법을 보여줍니다.

예제 코드:

#include <algorithm>
#include <iostream>
#include <map>
#include <string>

int main() {
  const std::map<std::string, int> numbers{
      {"Saad", 22}, {"Zaryab", 23}, {"Zeeshan", 24}};

  std::for_each(std::begin(numbers), std::end(numbers), [](const auto& entry) {
    std::cout << "Name: " << entry.first << "   Age: " << entry.second << '\n';
  });
}

GCC 11.1.0은 이 데모에서 사용되는 컴파일러의 이름입니다.

출력:

Name: Saad   Age: 22
Name: Zaryab   Age: 23
Name: Zeeshan   Age: 24

y_combinator를 사용하는 C++ 재귀 Lambda 함수

익명 함수(람다라고도 함)는 논리가 간단하고 명명된 함수로 추출되어야 하는 경우에만 사용하기 위한 것이므로 람다 내에서 재귀 호출이 이루어질 가능성은 거의 없습니다.

그러나 재귀를 사용할 수 없다고 상상해 봅시다. 함수가 우리 언어에서 일급 시민으로 취급되는 한(변수에 할당되고, 인수로 제공되고, 다른 객체처럼 반환될 수 있음) 우리는 여전히 재귀 구현을 작성할 수 있습니다.

Y 결합자는 이러한 목적에 유용한 고차 함수입니다. 불길하게 들리는 이름에도 불구하고 다른 함수를 감싸는 함수인 고차 함수일 뿐입니다.

다음은 피보나치 수열을 나열하기 위해 y 결합자를 사용하여 재귀 람다 함수를 생성한 예입니다.

예제 코드:

#include <iostream>

template <typename Function>
struct YCombinator {
  Function yFunction;

  template <typename... Args>
  decltype(auto) operator()(Args&&... args) {
    return yFunction(*this, std::forward<Args>(args)...);
  }
};

template <typename Function>
decltype(auto) make_YCombinator(Function f) {
  return YCombinator<Function>{f};
}

int main() {
  auto fib = make_YCombinator([](auto self, int n) {
    if (n < 2) return 1;
    return self(n - 1) + self(n - 2);
  });

  for (int i = 0; i < 10; ++i)
    std::cout << "fib(" << i << ") = " << fib(i) << "\n";

  return 0;
}

GCC 11.1.0은 이 데모에서 사용되는 컴파일러의 이름입니다.

출력:

fib(0) = 1
fib(1) = 1
fib(2) = 2
fib(3) = 3
fib(4) = 5
fib(5) = 8
fib(6) = 13
fib(7) = 21
fib(8) = 34
fib(9) = 55
작가: Saad Aslam
Saad Aslam avatar Saad Aslam avatar

I'm a Flutter application developer with 1 year of professional experience in the field. I've created applications for both, android and iOS using AWS and Firebase, as the backend. I've written articles relating to the theoretical and problem-solving aspects of C, C++, and C#. I'm currently enrolled in an undergraduate program for Information Technology.

LinkedIn

관련 문장 - C++ Lambda