ventajas programacion orientada objetos logica funcional ejemplos desventajas bases c functional-programming

programacion - ¿Qué herramientas hay para la programación funcional en C?



programacion funcional vs orientada a objetos (13)

He estado pensando mucho últimamente sobre cómo hacer la programación funcional en C ( no en C ++). Obviamente, C es un lenguaje de procedimiento y realmente no es compatible con la programación funcional de forma nativa.

¿Hay algún compilador / extensiones de lenguaje que agreguen algunas construcciones de programación funcional al lenguaje? GCC proporciona funciones anidadas como una extensión de idioma; las funciones anidadas pueden acceder a las variables desde el marco de la pila padre, pero esto todavía está muy lejos de los cierres maduros.

Por ejemplo, una cosa que creo que podría ser realmente útil en C es que en cualquier lugar donde se espera un puntero a función, podría pasar una expresión lambda, creando un cierre que se descompone en un puntero de función. C ++ 0x va a incluir expresiones lambda (que creo que es increíble); sin embargo, estoy buscando herramientas aplicables a C.

[Editar] Para aclarar, no estoy tratando de resolver un problema particular en C que sería más adecuado para la programación funcional; Simplemente tengo curiosidad sobre qué herramientas hay disponibles si quisiera hacerlo.


¿Qué tiene que ver con C que desea que sea funcional, la sintaxis o la semántica? La semántica de la programación funcional sin duda podría agregarse al compilador de C, pero para cuando hayas terminado, tendrás esencialmente el equivalente de uno de los lenguajes funcionales existentes, como Scheme, Haskell, etc.

Sería mejor utilizar el tiempo para aprender la sintaxis de aquellos lenguajes que soportan directamente esa semántica.


Bueno, algunos lenguajes de programación están escritos en C. Y algunos de ellos soportan funciones como ciudadanos de primera clase, los lenguajes en esa área son ecl (embbedabble common lisp IIRC), Gnu Smalltalk (gst) (Smalltalk tiene bloques), luego hay bibliotecas para "cierres", por ejemplo, en glib2 http://library.gnome.org/devel/gobject/unstable/chapter-signal.html#closure que al menos se acercó a la programación funcional. Entonces, quizás usar algunas de esas implementaciones para hacer programación funcional puede ser una opción.

Bien o puedes ir a aprender Ocaml, Haskell, Mozart / Oz o similares ;-)

Saludos


El lenguaje Félix se compila en C ++. Tal vez eso podría ser un paso adelante, si no te importa C ++.



La forma en que hice la programación funcional en C fue escribir un intérprete de lenguaje funcional en C. Lo llamé Fexl, que es la abreviatura de "Function EXpression Language".

El intérprete es muy pequeño, compilando hasta 68K en mi sistema con -O3 habilitado. Tampoco es un juguete; lo estoy usando para todo el nuevo código de producción que escribo para mi negocio (contabilidad basada en web para asociaciones de inversión).

Ahora escribo el código C solo para (1) agregar una función incorporada que llame a una rutina del sistema (por ejemplo, fork, exec, setrlimit, etc.), o (2) optimizar una función que de otro modo podría escribirse en Fexl (por ejemplo, búsqueda para una subcadena).

El mecanismo del módulo se basa en el concepto de un "contexto". Un contexto es una función (escrita en Fexl) que asigna un símbolo a su definición. Cuando lee un archivo Fexl, puede resolverlo con el contexto que desee. Esto le permite crear entornos personalizados o ejecutar código en un "entorno limitado" restringido.

http://fexl.com


La programación funcional no se trata de lambdas, se trata de funciones puras. Por lo tanto, los siguientes ampliamente promueven el estilo funcional:

  1. Solo use argumentos de función, no use estado global.

  2. Minimice los efectos secundarios, es decir, printf o cualquier IO. Devuelve datos que describen IO que pueden ejecutarse en lugar de causar los efectos secundarios directamente en todas las funciones.

Esto se puede lograr en simple c, sin necesidad de magia.


Lo principal que viene a la mente es el uso de generadores de código. ¿Estaría dispuesto a programar en un idioma diferente que proporcionara la programación funcional y luego generar el código C a partir de eso?

Si esa no es una opción atractiva, entonces podrías abusar de CPP para obtener parte del camino hasta allí. El macro sistema debería permitirle emular algunas ideas de programación funcional. He escuchado decir que gcc está implementado de esta manera, pero nunca lo he comprobado.

Por supuesto, C puede pasar funciones en torno al uso de indicadores de función, los principales problemas son la falta de cierres y el sistema tipo tiende a interponerse en el camino. Puede explorar macro sistemas más potentes que CPP, como M4. Supongo que, en última instancia, lo que estoy sugiriendo es que C verdadero no está a la altura de la tarea sin un gran esfuerzo, pero podrías extender C para que esté a la altura de la tarea. Esa extensión se vería más como C si usa CPP o podría ir al otro extremo del espectro y generar código C desde algún otro idioma.



No sé sobre C. Sin embargo, hay algunas características funcionales en Objective-C, GCC en OSX también admite algunas características, sin embargo, recomendaría de nuevo comenzar a utilizar un lenguaje funcional. Hay muchas más mencionadas anteriormente. Personalmente comencé con el esquema, hay algunos excelentes libros como The Little Schemer que pueden ayudarte a hacerlo.


Puede usar las funciones anidadas de GCC para simular expresiones lambda, de hecho, tengo una macro para hacerlo por mí:

#define lambda(return_type, function_body) / ({ / return_type anon_func_name_ function_body / anon_func_name_; / })

Use esto:

int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });


Requisito previo para el estilo de programación funcional es una función de primera clase. Se podría simular en C portátil si tolera el siguiente:

  • gestión manual de enlaces de alcance léxico, también conocidos como cierres.
  • gestión manual de variables de funcionamiento de por vida.
  • sintaxis alternativa de la aplicación / llamada a la función.

/* * with constraints desribed above we could have * good approximation of FP style in plain C */ int increment_int(int x) { return x + 1; } WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS(increment, increment_int); map(increment, list(number(0), number(1)); // --> list(1, 2) /* composition of first class function is also possible */ function_t* computation = compose( increment, increment, increment ); *(int*) call(computation, number(1)) == 4;

el tiempo de ejecución para dicho código podría ser tan pequeño como el siguiente

struct list_t { void* head; struct list_t* tail; }; struct function_t { void* (*thunk)(list_t*); struct list_t* arguments; } void* apply(struct function_t* fn, struct list_t* arguments) { return fn->thunk(concat(fn->arguments, arguments)); } /* expansion of WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS */ void* increment_thunk(struct list_t* arguments) { int x_arg = *(int*) arguments->head; int value = increment_int(x_arg); int* number = malloc(sizeof *number); return number ? (*number = value, number) : NULL; } struct function_t* increment = &(struct function_t) { increment_thunk, NULL }; /* call(increment, number(1)) expands to */ apply(increment, &(struct list_t) { number(1), NULL });

En esencia, imitamos la función de primera clase con cierres representados como un par de funciones / argumentos más un montón de macros. El código completo se puede encontrar here .


Si desea implementar cierres, tendrá que prepararse con lenguaje ensamblador e intercambio / gestión de pila. No recomendando en contra, simplemente diciendo que eso es lo que tendrás que hacer.

Sin embargo, no está seguro de cómo manejará las funciones anónimas en C. Sin embargo, en una máquina de von Neumann podría hacer funciones anónimas en asm.


FFCALL permite construir cierres en C - callback = alloc_callback(&function, data) devuelve un puntero de función de modo que la callback(arg1, ...) es equivalente a la function(data, arg1, ...) llamada function(data, arg1, ...) . Sin embargo, tendrás que manejar la recolección de basura manualmente.

Relacionado, los blocks se han agregado al tenedor de Apple de GCC; no son indicadores de función, pero le permiten pasar lambdas mientras evita la necesidad de construir y almacenar de forma gratuita las variables capturadas a mano (de hecho, ocurre algo de copia y recuento de referencias, escondido detrás de algunas bibliotecas sintácticas de azúcar y tiempo de ejecución).