如何在C中实现这个熟悉的功能?

时间:2011-09-16 17:45:40

标签: c lambda functional-programming lisp currying

考虑使用S-expr表示法编写的以下代码段:

(lambda (x) (lambda (y) (+ x y)))

或在Javascript中:

function(x) { return function(y) { return x+y; }; }

如何用C语言写这个?

5 个答案:

答案 0 :(得分:8)

这在C中很难做到,因为它依赖于闭包。使用C,你必须传递一个显式的上下文,所以你可能会得到类似的东西。

#include <stdio.h>

struct closure {
    int saved_x;
    int (*function)(struct closure, int);
};

int second_half_add(struct closure context, int y) {
    return context.saved_x + y;
}

struct closure curried_add(int x) {
    struct closure ret;
    ret.saved_x = x;
    ret.function = second_half_add;
    return ret;
}

int main() {
    struct closure context = curried_add(3);
    printf("%d\n", context.function(context, 4));
}

这真的太丑了,你几乎失去了所有的好处,但是有可能

答案 1 :(得分:3)

C没有头等功能,所以答案是:无论如何。

答案 2 :(得分:1)

这取决于你说“C”时的意思。

假设你真的想要通过简单的函数应用程序获得一些可以调用的东西,ISO C使得这样的事情变得非常困难 - 如果你真的想要保持在标准的混淆范围内并且不使用某些东西可能是不可能的low-level assembly tricks

然而,

Clang实现了non-standard support for closures实际上使这些事情成为可能。使用此功能,您的示例可以通过以下方式实现:

#include <stdio.h>
#include <stdlib.h>
#include <Block.h>

int (^plus(int x))() {
  return Block_copy(^(int y) {
    return x + y;
  });
}

int main() {
  int (^plus2)(int) = plus(2);
  printf("2 + 3 = %d\n", plus2(3));
  Block_release(plus2);
  return EXIT_SUCCESS;
}

答案 3 :(得分:1)

嗯,你可以做到。它不漂亮。它是这样的:

typedef int (*intfuncint)(Env*, int);

// this is the "closure" block
typedef struct Env {
  int x;
  intfuncint f;
} env_t;

// this is the internal function
int sum(Env* me, int y){return me->x + y;}

// this is the external function
Env* foo(int x){
  Env* result = malloc(sizeof(*result));
  result->x = x;
  result->f = sum;
  return result;
}

使用它获得3和5的总和看起来像这样:

Env* p = foo(3); p->f(p, 5)

答案 4 :(得分:0)

你不能用c写它,原因有几个,主要是因为c不能那样工作。

如果这是一个家庭作业问题,你的老师可能会另外说......如:

struct functor {
  int x;
  functiontype* f;
}

int dofunctor(functor*, y) { ... }

但它的概括性很差,不值得做。

您可以使用其他类似c语言编写它 - 例如perl。

您可以在c ++中执行类似的操作 - 请参阅以下答案:

C++ Functors - and their uses