如何提升函数以在C中获取额外参数?

qle*_*nec 6 c haskell functional-programming clang

(我知道C不是以功能性的方式使用.但是,在学习了函数式编程之后,我的思维方式也有所不同.)

鉴于这些限制:

  • 没有嵌套函数,因为clang禁止它(所以没有lamda表达式)
  • 没有全局变量

我们可以想到一种提升函数f以获取额外参数以适合原型的方法,例如当f执行时,这个新参数会被忽略吗?

这里详细介绍了我想要做的事情:

我想要拟合一个函数f,其类型是:

f :: void f(char *s)
Run Code Online (Sandbox Code Playgroud)

在一个函数g中,它接受一个函数作为参数(称之为arg),其类型为:

arg :: void f(unsigned int i, char *s)
Run Code Online (Sandbox Code Playgroud)

因此,g的类型是:

g :: void g(void (*f) (unsigned int, char))
Run Code Online (Sandbox Code Playgroud)

haskell中的解决方案如下:

g (const f)
Run Code Online (Sandbox Code Playgroud)

这是否可能,也许是某种宏观魔法?

编辑:为了更好地理解,这里是实际的代码.需要完成ft_striter的主体.目的是:将函数f应用于字符串的每个字符,使用或不使用其索引i.

void        ft_striter(char *s, void (*f) (char *s))
{
    ft_striteri(?);
}

static void ft_striteri_helper(char *s, unsigned int i, void (*f)(unsigned int, char*))
{
    if (*s) 
    {
        f(i, s);
        ft_striteri_helper(s + 1, i + 1, f);
    }
}

void        ft_striteri(char *s, void (*f)(unsigned int, char*))
{
    ft_striteri_helper(s, 0, f);
}
Run Code Online (Sandbox Code Playgroud)

Rei*_*ton 4

您无法在标准可移植 C 中实现此功能。问题在于该函数g. 设计错误。它应该有类型

void g(void (*f) (void *, unsigned int, char), void *ctxt)
Run Code Online (Sandbox Code Playgroud)

并且它应该将其ctxt参数作为f其进行的任何调用的第一个参数传递。

现在你可以用类似的代码实现你想要的

struct const_ctxt {
    void (*fun)(char *);
}

void const(void *ctxt, unsigned int i, char *s)
{
    ((struct const_ctxt *)ctxt)->fun(s);
}

void call_g_using_const_f(void (*f)(char *))
{
    struct const_ctxt *ctxt = malloc(sizeof (struct const_ctxt));
    ctxt->fun = f;
    g(const, (void *)ctxt);
    free(ctxt);
}
Run Code Online (Sandbox Code Playgroud)

警告:如果 的参数g可能超出 的动态范围,g那么您将需要找到另一种策略来管理 s 的分配ctxt

采用一对代码指针和数据“上下文”/“环境”指针的模式g是高级语言通常实现闭包的方式。