HOWTO · C++
C++의 재귀 Lambda 함수
이 기사에서는 C++ 프로그래밍 언어의 재귀 람다 함수를 이해합니다.
이 페이지의 내용
이 기사에서는 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