transparencia referencial programaciĆ³n programacion principios objetivo futuro funcional ejemplo bases aprender aplicaciones c++ functional-programming

c++ - referencial - programacion funcional el futuro



ProgramaciĆ³n Funcional en C++ (6)

Actualización de agosto de 2014: esta respuesta se publicó en 2009. C ++ 11 mejoró considerablemente las cosas para la programación funcional en C ++, por lo que esta respuesta ya no es precisa. Lo dejo abajo para un registro histórico.

Dado que esta respuesta quedó como la aceptada, la convertiré en una Wiki de la comunidad. Siéntase libre de mejorar colaborativamente para agregar consejos reales sobre programación de funciones con C ++ moderno.

No se puede hacer una verdadera programación funcional con C ++. Todo lo que puedes hacer es aproximarlo con una gran cantidad de dolor y complejidad (aunque en C ++ 11 es un poco más fácil). Por lo tanto, este enfoque no es recomendable. C ++ es compatible con otros paradigmas de programación relativamente bien, y en mi humilde opinión no debería inclinarse por los paradigmas que admite menos; al final, hará que el código ilegible solo lo entienda el autor.

¿Alguien puede guiarme cómo funciona la programación en C ++? ¿Hay algún buen material en línea al que pueda referirme?

Tenga en cuenta que sé sobre la biblioteca FC ++. Quiero saber cómo hacer eso solo con la biblioteca estándar de C ++.

Gracias.


Considera mis 4 proyectos de investigación:

Este proyecto es un prototipo funcional del juego ''Amber''. El código demuestra muchos de los principales conceptos funcionales: immutability , lambdas , monads , combinators , pure functions , declarative code design . Utiliza las características Qt C ++ y C ++ 11.

Para un ejemplo rápido, vea cómo las tareas pueden encadenarse en una gran tarea que modificará el mundo de Amber cuando se aplique:

const AmberTask tickOneAmberHour = [](const amber::Amber& amber) { auto action1Res = magic::anyway(inflateShadowStorms, magic::wrap(amber)); auto action2Res = magic::anyway(affectShadowStorms, action1Res); auto action3Res = magic::onFail(shadowStabilization, action2Res); auto action4Res = magic::anyway(tickWorldTime, action3Res); return action4Res.amber; };

Este es un escaparate de lentes funcionales genéricas en C ++. La implementación está construida con el uso de Variadic Templates , algunos intrincados (y válidos) hacks de C ++ para hacer las lentes compostables y aseadas. La biblioteca es solo una demostración de la charla y, por lo tanto, proporciona solo algunos de los más importantes combinadores, a saber: set() , view() , traverse() , bind() , infijo literal combinator, over() y otros.

(Tenga en cuenta que existe el project ''Lentes C ++'': pero no se trata de ''lentes'' reales, se trata de propiedades de clase con getters y setters en sentido de C # o propiedades de Java).

Ejemplo rápido

Car car1 = {"x555xx", "Ford Focus", 0, {}}; Car car2 = {"y555yy", "Toyota Corolla", 10000, {}}; std::vector<Car> cars = {car1, car2}; auto zoomer = traversed<Car>() to modelL(); std::function<std::string(std::string)> variator = [](std::string) { return std::string("BMW x6"); }; std::vector<Car> result = over(zoomer, cars, variator); QVERIFY(result.size() == 2); QVERIFY(result[0].model == "BMW x6"); QVERIFY(result[1].model == "BMW x6");

Probablemente has escuchado sobre las mónadas. Las mónadas están en todas partes en conversaciones sobre programación funcional ahora. Es una palabra de moda. ¿Pero qué hay de las comonads? Presenté autómatas celulares 1D y 2D con el concepto de comonads bajo el capó. El objetivo era mostrar cuán fácil es pasar del código de flujo único al paralelo utilizando std :: future como mónada Par. El proyecto también compara y compara dos de estos enfoques.

Ejemplo rápido

template <typename A, typename B> UUB fmap( const func<B(UUA)>& f, const UUUUA& uuu) { const func<UB(UUUA)> f2 = [=](const UUUA& uuu2) { UB newUt; newUt.position = uuu2.position; newUt.field = fp::map(f, uuu2.field); return newUt; }; return { fp::map(f2, uuu.field), uuu.position }; }

Esta biblioteca se basa en la Free monad y algunas otras ideas avanzadas de programación funcional. Su interfaz es similar a la biblioteca STM nativa de Haskell. Las transacciones son compostables monádicamente, funcional puro, y hay una gran cantidad de combinadores monádicos útiles para hacer más conveniente y poderoso el diseño de un modelo concurrente. Implementé el problema de los Filósofos del comedor usando la biblioteca, y funciona bien. Aquí hay una muestra de alguna transacción para tomar de tenedores por un filósofo:

STML<Unit> takeFork(const TFork& tFork) { return withTVar<Fork, Unit>(tFork, [=](const Fork& fork) { if (fork.state == ForkState::Free) { return writeTVar<Fork>(tFork, Fork {fork.name, ForkState:Taken}); } else { return retry<Unit>(); } }); } STML<Unit> takeForks(const TForkPair& forks) { STML<Unit> lm = takeFork(forks.left); STML<Unit> rm = takeFork(forks.right); return sequence(lm, rm); }


Hay un libro llamado Functional C por Pieter Hartel y Henk Muller que podría ayudar. Si todavía está disponible. Un enlace a alguna información sobre esto está here . IIRC no fue tan malo.


No creo que puedas hacer una programación verdadera, real y funcional en C ++; pero ciertamente no es la forma más fácil o natural de usarlo. Además, puede usar un par de modismos funcionales y no toda la mentalidad (es decir, "estilo fluido")

Mi consejo sería aprender un lenguaje funcional, tal vez comenzar con Scheme, luego pasar a Haskell. Luego usa lo que has aprendido al programar en C ++. tal vez no uses un estilo funcional obvio; pero puede obtener las mayores ventajas (es decir, usar estructuras inmutables).


Probablemente un poco tarde, pero para cualquier otra persona que busque, utilizo lua como una extensión de programación funcional para C ++ y es genial. lua


Puede lograr una sorprendente cantidad de estilo de "programación funcional" con C ++ moderno. De hecho, el lenguaje ha tenido una tendencia en esa dirección desde su ''estandarización''.

La biblioteca estándar contiene algoritmos análogos a map, reduce, etc (for_each, transform, adjacent_sum ...). La próxima revisión, C ++ 0x, contiene muchas características diseñadas para que los programadores puedan trabajar con ellas en un estilo más funcional (expresiones lambda, etc.).

Mire en las diversas bibliotecas de Boost para más diversión. Solo para ilustrar que el estándar C ++ contiene un montón de bondad funcional, aquí hay una función factorial en el estilo de continuación de paso en C ++ estándar.

#include <iostream> // abstract base class for a continuation functor struct continuation { virtual void operator() (unsigned) const = 0; }; // accumulating continuation functor struct accum_cont: public continuation { private: unsigned accumulator_; const continuation &enclosing_; public: accum_cont(unsigned accumulator, const continuation &enclosing) : accumulator_(accumulator), enclosing_(enclosing) {}; virtual void operator() (unsigned n) const { enclosing_(accumulator_ * n); }; }; void fact_cps (unsigned n, const continuation &c) { if (n == 0) c(1); else fact_cps(n - 1, accum_cont(n, c)); } int main () { // continuation which displays its'' argument when called struct disp_cont: public continuation { virtual void operator() (unsigned n) const { std::cout << n << std::endl; }; } dc; // continuation which multiplies its'' argument by 2 // and displays it when called struct mult_cont: public continuation { virtual void operator() (unsigned n) const { std::cout << n * 2 << std::endl; }; } mc; fact_cps(4, dc); // prints 24 fact_cps(5, mc); // prints 240 return 0; }

Ok, mentí un poco. Es un factorial functor . Después de todo, los cierres son objetos de un pobre hombre ... y viceversa. La mayoría de las técnicas funcionales utilizadas en C ++ se basan en el uso de funtores (es decir, objetos funcionales); esto se verá de forma extensiva en el STL.