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.




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




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.




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 .




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.







Links