Función Lambda recursiva en C++

Saad Aslam 12 octubre 2023
  1. Función Lambda recursiva de C++
  2. Función Lambda recursiva de C++ usando std::function
  3. Función Lambda recursiva de C++ usando Lambda genérica
  4. Función Lambda recursiva de C++ usando y_combinator
Función Lambda recursiva en C++

En este artículo, entenderemos las lambdas recursivas disponibles en C++.

Función Lambda recursiva de C++

La recursividad se refiere a un proceso por el cual una función (directa o indirectamente) se llama a sí misma, y la función correspondiente a este proceso se llama Función Recursiva. Una expresión lambda recursiva es el resultado de este proceso.

Cuando algunos problemas se abordan utilizando un método recursivo, son mucho más simples de resolver.

En el proceso de reestructuración del código local, las lambdas son una herramienta útil. Por otro lado, hay casos en los que deseamos utilizar la lambda desde dentro de sí mismo.

Esto se puede hacer por una de dos razones: para habilitar la recursión directa o para hacer posible que el cierre se registre como una continuación. La versión actual de C++ hace que esta tarea sea extremadamente difícil de realizar con éxito.

Implementación de la Función Lambda Recursiva en C++

En el primer paso, importaremos las bibliotecas necesarias.

#include <functional>
#include <iostream>

Dentro de la función main(), inicializa una variable de tipo int y asígnale un valor entero.

int main() { int anyNumber = 456789; }

Luego, crea una función con el tipo void y asígnale el nombre reverseByRecursiveLambda.

function<void()> reverseByRecursiveLambda;

Ahora, inicialice la función reverseByRecursiveLambda con una función lambda recursiva.

reverseByRecursiveLambda = [&]() {};

Dentro de este método, debe implementar una verificación que diga que si el valor entero de anyNumber es igual a 0, no debe devolver nada. Si este no es el caso, la función debe continuar con el siguiente conjunto de operaciones.

Luego, la función realizará una serie de cálculos matemáticos, luego de lo cual imprimirá los resultados. Como último paso, ejecutará de nuevo la función denominada reverseByRecursiveLambda().

if (anyNumber == 0) return;

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

Después de que esta función haya completado la ejecución, lo único que se requiere es una llamada a esta función dentro del método main().

int main() { reverseByRecursiveLambda(); }

Código fuente completo:

#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();
}

Producción :

9 8 7 6 5 4 3 2 1

Función Lambda recursiva de C++ usando std::function

La plantilla de clase std::function es un envoltorio de función polimórfica que se puede utilizar para diversos fines. Cualquier expresión lambda, expresiones de enlace u otros objetos de función pueden almacenarse, copiarse e invocarse dentro de instancias de la clase std::function.

Además, estas instancias pueden contener punteros a funciones miembro y punteros a miembros de datos.

En el siguiente ejemplo, debemos tomar una instantánea del factorial, después de lo cual podemos hacer referencia a él dentro del cuerpo lambda.

Código de ejemplo:

#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);
}

Producción :

The factorial of 5 is: 120

Función Lambda recursiva de C++ usando Lambda genérica

La expresión Lambda genérica hace referencia a una expresión lambda con al menos un argumento del tipo auto.

No se requiere el uso de std::function para crear funciones lambda recursivas, gracias a la expresión lambda genérica, que hizo posible esta opción. El tipo de una expresión lambda no se puede determinar solo por su nombre.

Por lo tanto, antes del lanzamiento de C++14, se requería incluir una expresión lambda recursiva dentro de una función estándar::. No depende de std::function, y no necesita capturar ningún dato para funcionar correctamente en cualquier tipo de base numérica.

En el ejemplo, demostraremos cómo mostrar los datos almacenados en un mapa usando la lambda genérica auto.

Código de ejemplo:

#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 es el nombre del compilador que se utiliza en esta demostración.

Producción :

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

Función Lambda recursiva de C++ usando y_combinator

Dado que las funciones anónimas (también conocidas como lambdas) solo deben usarse cuando la lógica es directa y deben extraerse a una función con nombre, es poco probable que se realice una llamada recursiva dentro de una lambda.

Sin embargo, imaginemos que no podemos utilizar la recursividad. Siempre que las funciones se traten como ciudadanos de primera clase en nuestro lenguaje (pueden asignarse a variables, proporcionarse como argumentos y devolverse como cualquier otro objeto), aún podemos escribir nuestra implementación de recursividad.

El combinador Y es una función de orden superior útil para este propósito. A pesar de su nombre que suena siniestro, es solo una función de orden superior, una función que se envuelve alrededor de otra función.

El siguiente es un ejemplo de creación de una función lambda recursiva utilizando el combinador y para listar la serie de Fibonacci.

Código de ejemplo:

#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 es el nombre del compilador que se utiliza en esta demostración.

Producción :

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
Autor: 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

Artículo relacionado - C++ Lambda