qle*_*nec 6 c haskell functional-programming clang
(我知道C不是以功能性的方式使用.但是,在学习了函数式编程之后,我的思维方式也有所不同.)
鉴于这些限制:
我们可以想到一种提升函数f以获取额外参数以适合原型的方法,例如当f执行时,这个新参数会被忽略吗?
这里详细介绍了我想要做的事情:
我想要拟合一个函数f,其类型是:
f :: void f(char *s)
在一个函数g中,它接受一个函数作为参数(称之为arg),其类型为:
arg :: void f(unsigned int i, char *s)
因此,g的类型是:
g :: void g(void (*f) (unsigned int, char))
haskell中的解决方案如下:
g (const f)
这是否可能,也许是某种宏观魔法?
编辑:为了更好地理解,这里是实际的代码.需要完成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);
}
您无法在标准可移植 C 中实现此功能。问题在于该函数g. 设计错误。它应该有类型
void g(void (*f) (void *, unsigned int, char), void *ctxt)
并且它应该将其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);
}
警告:如果 的参数g可能超出 的动态范围,g那么您将需要找到另一种策略来管理 s 的分配ctxt。
采用一对代码指针和数据“上下文”/“环境”指针的模式g是高级语言通常实现闭包的方式。