Как эта знакомая функция реализована в C? - PullRequest
3 голосов
/ 16 сентября 2011

Рассмотрим следующий сегмент кода, написанный в нотации S-expr:

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

или в Javascript:

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

Как мне написать это на C?

Ответы [ 5 ]

8 голосов
/ 16 сентября 2011

Это трудно сделать в 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));
}

Это действительно безобразно, и вы теряете почти все преимущества карри, но это возможно

3 голосов
/ 16 сентября 2011

C не имеет функций первого класса, поэтому ответ: нет.

1 голос
/ 16 сентября 2011

Ну, вы можете сделать это. Это не красиво. Это выглядит примерно так:

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)
1 голос
/ 16 сентября 2011

Это зависит от того, что вы имеете в виду, когда говорите «С».

Предполагая, что вы действительно хотите получить что-то, что вы можете вызвать с помощью простого приложения-функции, ISO C делает такую ​​вещь довольно трудной для выполнения - возможно, невозможной, если вы действительно хотите оставаться в рамках стандарта и не использовать некоторые из них. низкоуровневые сборочные приемы .

Clang , однако, реализует нестандартную поддержку замыканий , которая фактически делает такие вещи возможными. Используя эту функцию, ваш пример может быть реализован следующим образом:

#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;
}
0 голосов
/ 16 сентября 2011

Вы не можете написать это в c по нескольким причинам, в основном из-за того, что c просто так не работает.

Если это домашний вопрос, ваш учитель может сказать иначе ... что-то вроде

struct functor {
  int x;
  functiontype* f;
}

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

Но он обобщается настолько плохо, что делать его не стоит.

Вы можете написать его на некоторых других c-подобных языках - таких как perl.сделать что-то подобное в C ++ - см. следующий ответ:

Функторы C ++ - и их использование

...