Quali strumenti ci sono per la programmazione funzionale in C?


Answers

È possibile utilizzare le funzioni nidificate di GCC per simulare le espressioni lambda, infatti, ho una macro per farlo per me:

#define lambda(return_type, function_body) \
  ({ \
    return_type anon_func_name_ function_body \
    anon_func_name_; \
  })

Usa in questo modo:

int (*max)(int, int) = lambda (int, (int x, int y) { return x > y ? x : y; });
Question

Ultimamente ho pensato molto a come fare la programmazione funzionale in C ( non in C ++). Ovviamente, C è un linguaggio procedurale e in realtà non supporta la programmazione funzionale in modo nativo.

Esistono estensioni di compilatore / lingua che aggiungono alcuni costrutti di programmazione funzionale al linguaggio? GCC fornisce funzioni annidate come estensione del linguaggio; le funzioni annidate possono accedere alle variabili dal frame dello stack genitore, ma questo è ancora molto lontano dalle chiusure mature.

Ad esempio, una cosa che penso possa essere davvero utile in C è che ovunque sia previsto un puntatore a funzione, potresti essere in grado di passare un'espressione lambda, creando una chiusura che decompone in un puntatore a funzione. C ++ 0x includerà espressioni lambda (che penso sia stupenda); tuttavia, sto cercando strumenti applicabili alla scala C.

[Modifica] Per chiarire, non sto cercando di risolvere un particolare problema in C che sarebbe più adatto alla programmazione funzionale; Sono semplicemente curioso di sapere quali strumenti sono disponibili se volessi farlo.




Non so su C. Ci sono alcune caratteristiche funzionali in Objective-C, anche se GCC su OSX supporta anche alcune funzionalità, tuttavia consiglierei di nuovo di iniziare a usare un linguaggio funzionale, ci sono molte cose sopra menzionate. Ho iniziato personalmente con lo schema, ci sono alcuni libri eccellenti come The Little Schemer che possono aiutarti a farlo.




Il linguaggio Felix si compila in C ++. Forse potrebbe essere una pietra miliare, se non ti dispiace C ++.




Se si desidera implementare chiusure, è necessario familiarizzarsi con il linguaggio assembly e lo stack swap / gestione. Non raccomandare contro di esso, solo dicendo che è quello che devi fare.

Non sei sicuro di come gestirai le funzioni anonime in C. Su una macchina di von Neumann, potresti comunque eseguire funzioni anonime in asm.







Prerequisito per lo stile di programmazione funzionale è una funzione di prima classe. Potrebbe essere simulato in portatile C se si tollerano i seguenti:

  • gestione manuale delle associazioni di scope lessicali, note anche come chiusure.
  • gestione manuale delle variabili funzionali a vita.
  • sintassi alternativa dell'applicazione / chiamata di funzione.
/* 
 * with constraints desribed above we could have
 * good approximation of FP style in plain C
 */

int increment_int(int x) {
  return x + 1;
}

WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS(increment, increment_int);

map(increment, list(number(0), number(1)); // --> list(1, 2)


/* composition of first class function is also possible */

function_t* computation = compose(
  increment,
  increment,
  increment
);

*(int*) call(computation, number(1)) == 4;

runtime per tale codice potrebbe essere piccolo come uno di seguito

struct list_t {
  void* head;
  struct list_t* tail;
};

struct function_t {
   void* (*thunk)(list_t*);
   struct list_t* arguments;
}

void* apply(struct function_t* fn, struct list_t* arguments) {
  return fn->thunk(concat(fn->arguments, arguments));
}

/* expansion of WRAP_PLAIN_FUNCTION_TO_FIRST_CLASS */
void* increment_thunk(struct list_t* arguments) {
  int x_arg = *(int*) arguments->head;
  int value = increment_int(x_arg);
  int* number = malloc(sizeof *number);

  return number ? (*number = value, number) : NULL;
}

struct function_t* increment = &(struct function_t) {
  increment_thunk,
  NULL
};

/* call(increment, number(1)) expands to */
apply(increment, &(struct list_t) { number(1), NULL });

In sostanza imitiamo la funzione di prima classe con le chiusure rappresentate come coppia di funzioni / argomenti più il mazzo di macrose. Il codice completo potrebbe essere trovato here .