C中有哪些用于函数式编程的工具?
最近我一直在想如何去做C语言的函数式编程( 而不是 C ++)。 显然,C是一种程序语言,并不真正支持本地的函数式编程。
是否有任何编译器/语言扩展,为语言添加一些function性的编程结构? GCC提供嵌套函数作为语言扩展; 嵌套函数可以从父堆栈帧访问variables,但是这与成熟闭包仍然有很大的距离。
例如,我认为有一件事情在C中可能非常有用,那就是在任何需要函数指针的地方,你都可以传递一个lambdaexpression式,创build一个闭合函数,将其衰减到一个函数指针中。 C ++ 0x将包括lambdaexpression式(我认为是真棒); 不过,我正在寻找适用于直C的工具
为了澄清,我没有试图解决C中的一个特定的问题,这将更适合函数式编程。 我只是好奇,如果我想这样做,那里有什么工具。
FFCALL允许你在C中构build闭包 – callback = alloc_callback(&function, data)
返回一个函数指针,使得callback(arg1, ...)
等价于调用function(data, arg1, ...)
。 不过,您将不得不手动处理垃圾回收。
相关的,苹果的GCC分支已经添加了块 ; 它们不是函数指针,但它们可以让你传递lambdaexpression式,同时避免需要为手动捕获的variables构build和释放存储空间(有效地,一些复制和引用计数发生,隐藏在一些语法糖和运行时库后面)。
你可以使用GCC的嵌套函数来模拟lambdaexpression式,实际上,我有一个macros来为我做:
#define lambda(return_type, function_body) \ ({ \ return_type anon_func_name_ function_body \ anon_func_name_; \ })
像这样使用:
int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });
函数式编程不是关于lambdas,而是纯粹的函数。 所以下面广泛推介function风格:
-
只使用函数参数,不要使用全局状态。
-
最大限度地减less副作用,即printf或任何IO。 返回描述可以执行的IO的数据,而不是直接在所有函数中引起副作用。
这可以在普通的c中实现,不需要魔法。
Hartel&Muller的书C的function现在可以在(2012-01-02)find: http : //eprints.eemcs.utwente.nl/1077/ (有一个链接到PDF版本)。
主要想到的是使用代码生成器。 你愿意用提供函数式编程的不同语言进行编程,然后从中产生C代码吗?
如果这不是一个有吸引力的select,那么你可能会滥用CPP来获得部分途径。 macros观系统应该让你模仿一些function性的编程思想。 我听说gcc是这样实现的,但是我从来没有检查过。
当然C可以使用函数指针来传递函数,主要的问题是缺less闭包,并且types系统趋于阻碍。 你可以探索比CPP更强大的macros观系统,比如M4。 我想最终,我所说的是真正的C没有很大的努力就无法完成任务,但是你可以扩展C以使它能够完成任务。 如果你使用CPP,那么这个扩展看起来就像C一样,或者你可以去到另一端,从其他语言生成C代码。
如果你想实现闭包,你将不得不使用汇编语言和堆栈交换/pipe理。 不build议反对,只是说这是你必须做的。
不知道如何处理C中的匿名函数。在冯·诺依曼机上,你可以在asm中做匿名函数。
请看Hartel&Muller的书“ Functional C”
http://www.ub.utwente.nl/webdocs/ctit/1/00000084.pdf
http://www.cs.bris.ac.uk/~henkm/f2c/index.html
好几种编程语言都是用C语言编写的,其中一些支持一等公民的function,这方面的语言是ecl(可embedded的通用lisp IIRC),Gnu Smalltalk(gst)(Smalltalk有块),然后是库对于“封闭”,例如在glib2 http://library.gnome.org/devel/gobject/unstable/chapter-signal.html#closure至less有接近函数式编程。; 所以也许使用一些这些实现来做function编程可能是一个select。
那么或者你可以去学Ocaml,Haskell,莫扎特/奥兹等;-)
问候
Felix语言编译为C ++。 也许这可能是一个石阶,如果你不介意C ++。
函数式编程风格的先决条件是一stream的function。 如果你容忍下一个,它可以在便携式C中模拟:
- 词汇作用域绑定的手动pipe理,也就是closures。
- 手动pipe理函数variables的生命周期。
- 函数应用程序/调用的替代语法。
/* * 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;
这样的代码的运行时可能小到如下所示
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 });
从本质上讲,我们模仿了第一类函数,用闭合表示函数/参数对加上一堆macros。 完整的代码可以在这里find。
不知道C.虽然在Objective-C中有一些function特性,但OSX上的GCC也支持一些function,但是我会再次推荐使用function语言,上面提到了很多。 我个人以计划开始,有一些优秀的书籍,如小Schemer可以帮助你这样做。
C是什么,你想要function,语法或语义? 函数式编程的语义当然可以添加到C编译器中,但是当你完成的时候,你基本上可以使用现有的函数式语言之一,比如Scheme,Haskell等等。
仅仅学习那些直接支持这些语义的语言的语法将会更好地利用时间。