Programación funcional en C++: nivel avanzado

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Programación funcional en C++: nivel avanzado



La programación funcional (PF) es un paradigma en el que los cálculos se representan como la evaluación de funciones matemáticas, evitando cambios de estado y datos mutables. Aunque C++ fue originalmente un lenguaje orientado a objetos y procedural, a partir del estándar C++11 recibió potentes herramientas para PF: expresiones lambda, std::function, std::bind, y en C++17 se agregó soporte para std::optional y std::variant, que permiten implementar patrones mónadicos. En este artículo exploraremos técnicas avanzadas de programación funcional en C++: composición de funciones, currying, trabajo con mónadas y creación de funciones puras utilizando las capacidades modernas del lenguaje.



1. Expresiones lambda y funciones puras



Las expresiones lambda son la base del estilo funcional en C++. Permiten crear funciones anónimas en el lugar, lo que es ideal para algoritmos de <algorithm>. Sin embargo, para una verdadera PF es importante que las lambdas sean puras — es decir, que no tengan efectos secundarios ni dependan de estado mutable externo.



#include <iostream>#include <vector>#include <algorithm>

int main() { std::vector<int> numbers = {1, 2, 3, 4, 5};

// Lambda pura: solo datos de entrada, solo salida auto square = [](int x) { return x * x; };

// Aplicamos transform sin efectos secundarios std::vector<int> squared; std::transform(numbers.begin(), numbers.end(), std::back_inserter(squared), square);

for (int n : squared) std::cout << n << " "; // 1 4 9 16 25 return 0;}


Para uso avanzado, se debe evitar la captura por referencia ([&]) a menos que sea crítico. La captura por valor ([=]) o la enumeración explícita de capturas hace que la lambda sea más predecible y testeable.



2. Composición de funciones con std::function y operadores



La composición es la combinación de dos o más funciones en una. En C++ se puede implementar composición usando plantillas y std::function. Veamos un compositor genérico:



#include <functional>#include <iostream>

template <typename F, typename G>auto compose(F f, G g) { return [f, g](auto x) { return f(g(x)); };}

int main() { auto addOne = [](int x) { return x + 1; }; auto multiplyByTwo = [](int x) { return x * 2; };

auto addThenMultiply = compose(multiplyByTwo, addOne); std::cout << addThenMultiply(5) << std::endl; // (5+1)*2 = 12

// Composición de múltiples funciones auto triple = compose(multiplyByTwo, compose(addOne, addOne)); std::cout << triple(5) << std::endl; // ((5+1)+1)*2 = 14 return 0;}


Para cadenas más complejas se puede usar el operador de tubería (similar a |> en otros lenguajes). En C++20 es posible sobrecargar operator| para crear una sintaxis conveniente:



#include <functional>#include <iostream>

template <typename F>class Pipeable { F f;public: Pipeable(F func) : f(func) {} template <typename T> auto operator()(T x) const { return f(x); }};

template <typename T, typename F>auto operator|(T x, Pipeable<F> p) { return p(x);}

int main() { auto addOne = Pipeable([](int x) { return x + 1; }); auto square = Pipeable([](int x) { return x * x; });

int result = 5 | addOne | square; // (5+1)^2 = 36 std::cout << result << std::endl; return 0;}


Este enfoque hace que el código sea declarativo y fácil de leer.



3. Currying y aplicación parcial



El currying es la transformación de una función de varios argumentos en

Blogs

Book Recommendations