Il modo "normale" di esprimere cosa sia una funzione pura è in termini di trasparenza referenziale . Una funzione è pura se è referenzialmente trasparente .
Trasparenza referenziale , grosso modo, significa che puoi sostituire la chiamata alla funzione con il suo valore di ritorno o viceversa in qualsiasi punto del programma, senza cambiare il significato del programma.
Quindi, ad esempio, se i C printffossero referenzialmente trasparenti, questi due programmi dovrebbero avere lo stesso significato:
printf("Hello");
e
5;
e tutti i seguenti programmi dovrebbero avere lo stesso significato:
5 + 5;
printf("Hello") + 5;
printf("Hello") + printf("Hello");
Perché printf restituisce il numero di caratteri scritti, in questo caso 5.
Diventa ancora più ovvio con le voidfunzioni. Se ho una funzione void foo, allora
foo(bar, baz, quux);
dovrebbe essere lo stesso di
;
Cioè poiché foonon restituisce nulla, dovrei essere in grado di sostituirlo con nulla senza cambiare il significato del programma.
È chiaro, quindi, che né printfné foosono referenzialmente trasparenti, e quindi nessuno dei due è puro. Infatti, una voidfunzione non può mai essere referenzialmente trasparente, a meno che non sia una no-op.
Trovo questa definizione molto più facile da gestire come quella che hai dato. Permette anche di applicarlo a qualsiasi granularità tu voglia: puoi applicarlo a singole espressioni, a funzioni, a interi programmi. Ti permette, ad esempio, di parlare di una funzione come questa:
func fib(n):
return memo[n] if memo.has_key?(n)
return 1 if n <= 1
return memo[n] = fib(n-1) + fib(n-2)
Possiamo analizzare le espressioni che compongono la funzione e concludere facilmente che non sono referenzialmente trasparenti e quindi non pure, poiché utilizzano una struttura dati mutabile, ovvero l' memoarray. Tuttavia, possiamo anche esaminare la funzione e vedere che è referenzialmente trasparente e quindi pura. Questa è talvolta chiamata purezza esterna , cioè una funzione che appare pura al mondo esterno, ma è implementata internamente impura.
Tali funzioni sono comunque utili, perché mentre l'impurità infetta tutto ciò che la circonda, l'interfaccia pura esterna costruisce una sorta di "barriera di purezza", dove l'impurità infetta solo le tre linee della funzione, ma non trapela nel resto del programma . Queste tre righe sono molto più facili da analizzare per la correttezza rispetto all'intero programma.