[英]Defining and calling higher-order function composition functions with function pointers in C
[英]Higher-order functions in C as a syntactic sugar with minimal effort
我想用C語言實現高階函數(HOF)作為語法糖,只需要很少的努力。 例如,對於以下代碼
function add(int x) {
return int(int y) {
return x + y;
};
}
int main() {
function add1 = add(1);
return add1(2);
}
它被轉換成純C作為
#include <stdlib.h>
typedef struct {
void *ctx;
void* (*fun)(void *arg, void *ctx);
} function;
function new_function(void *ctx, void* (*fun)(void *, void *)) {
function f = {.ctx=ctx, .fun=fun};
return f;
}
void* apply(function f, void *arg) {
return (*(f.fun))(arg, f.ctx);
}
typedef struct {
int x;
} context$1;
void* new_context$1(int x) {
context$1 *ctx = malloc(sizeof(context$1));
ctx->x = x;
return ctx;
}
void* function$1(void *arg, void *ctx) {
int y = (int)arg;
int x = ((context$1*)ctx)->x;
return (void*)(x + y);
}
function add(int x) {
return new_function(new_context$1(x), function$1);
}
int main() {
function add1 = add(1);
return (int)apply(add1, (void*)2);
}
我已經運行了這個(手動)轉換版本,它運行正常。 為了實現,我相信一些AST操作和lambda提升就足夠了。
我的方法有任何潛在的缺陷嗎? 是否有更簡單的HOF方法,或者我可以改進我的方法以使其更容易實現嗎?
現在有兩個明顯的問題:
請注意,生成的代碼會調用未定義的行為。 在幾個地方,您通過直接轉換在整數類型和指針類型之間進行轉換。 這在C中是不合法的。您無法保證指針和int
的大小相同,或者您甚至可以在它們之間進行轉換而不會更改或損壞該值。 代碼可能會巧合地在您的特定系統上運行,但它會在許多其他系統上中斷。
一般來說,只能處理指針和整數類型(以及結構)的唯一方法是使用可變長度參數列表傳遞參數。 這樣,無論基礎數據類型的大小如何,您都可以提取每個參數。
另一種選擇是刪除通用function
結構,並為代碼中的每個HOF創建自定義結構。 然后,函數指針可以直接列出所有必需的參數,而不是嘗試在通用接口后面抽象它們,這將消除有問題的強制轉換,並允許代碼按預期工作,而不管使用的數據類型如何。
就可用性而言,考慮更改您的接口,以便在聲明它的行上指定(或至少列出 )HOF的返回類型。 C對象總是在聲明中列出它們的類型。 在您的示例中,聲明是function add1 = add(1);
。 要找出此函數返回的數據類型,您必須深入了解HOF的定義。 對於示例代碼而言,這不是一項艱巨的任務,但對於更復雜的代碼而言,這可能並非易事。 如果HOF來自圖書館,您可能根本沒有HOF的代碼。 也許像function(int) add1 = add(1);
可能更明確。
另外,我建議您將自動生成的函數定義為static
以幫助防止模塊之間的名稱沖突。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.