Il looping nella programmazione funzionale non viene eseguito con istruzioni di controllo come for
e while
, è fatto con chiamate esplicite a funzioni come map
, fold
o ricorsione - tutte operazioni che prevedono il posizionamento del ciclo interno chiama all'interno di un'altra funzione . Se il codice di loop muta le variabili al di fuori del ciclo, questa funzione del ciclo interno manipolerebbe le variabili al di fuori del suo ambito e sarebbe quindi impura . Quindi l'intera funzione esterna è pura, ma il ciclo non lo è. I costrutti ciclici nella programmazione funzionale richiedono che lo stato sia esplicito. Tradurre il tuo codice in qualcosa usando gli strumenti di ciclo di programmazione funzionale rivela l'impurità:
int as_int(char *str)
{
int acc = 0; /* accumulate the partial result */
map(takeWhile(isdigit, str), void function(char *chr) {
acc = acc * 10 + (chr - '0');
});
return acc;
}
(Nota: questa sintassi è approssimativa per far passare l'idea generale)
Questo codice usa una funzione interna per il corpo del ciclo che deve mutare la variabile acc
, che è al di fuori del suo ambito. Questo è impuro - la funzione del ciclo interno dipende dal contesto del ciclo esterno , chiamandola più volte con lo stesso carattere avrà effetti collaterali e l'ordine che si chiama sulla sequenza di caratteri è importante. Nella programmazione funzionale, al fine di rendere questa una funzione pura, dovresti rendere questa dipendenza dallo stato passato tra iterazioni di loop esplicite con fold
:
int as_int(char *str)
{
return fold(takeWhile(isdigit, str), 0, int function(char *chr, int acc) {
return acc * 10 + (chr - '0');
});
}
fold
utilizza una funzione di due argomenti per il corpo del ciclo interno: il primo argomento è un elemento nella sequenza in cui fold
esegue il looping, mentre il secondo è un valore che il corpo del ciclo interno utilizza per creare risultati parziali. Per la prima iterazione del ciclo, acc
è 0, per il secondo, acc
è qualunque sia la prima chiamata di funzione del ciclo interno restituita, per il terzo, è qualunque sia il secondo ciclo interno restituito e il ciclo finale restituisce il risultato del % espressione fold
.
Nota che questo non è un problema con il tuo codice dal punto di vista del resto del tuo programma - entrambe le definizioni di as_int
sono pure. La differenza sta nel fatto che il codice del ciclo interno è una funzione pura, è possibile sfruttare la vasta gamma di strumenti offerti dalla programmazione funzionale per scomporre il ciclo in qualcosa di più dichiarativo (ad esempio utilizzando takeWhile, fold, filter, map, ecc. Ecc.)