La lettura di una variabile esterna produce una funzione impura?

1

Leggevo di "Riflessione referenziale" che dice come programmare pensando al purezza e al determinismo . Si dice che una funzione che modifica uno stato esterno non sia impura.

Ma che ne è di una funzione che legge solo uno stato esterno (come la lettura di una variabile globale), non è anche vero?

    
posta Isaac Ferreira 21.07.2018 - 16:12
fonte

3 risposte

4

Un'espressione è referenzialmente trasparente se possiamo sostituire l'espressione con il suo valore, senza modificare il comportamento del programma. Sotto questa definizione, una funzione è pura se possiamo sostituire qualsiasi chiamata a quella funzione con il suo valore di ritorno.

Se una funzione interagisce con una variabile esterna in un modo che influenza il malfunzionamento del programma, allora la funzione è impura - non solo la scrittura ma anche la lettura, se la variabile può essere modificata altrove: non è una variabile esterna che trasforma una funzione impura, ma stato esterno

Ad esempio, questa funzione JavaScript f è completamente pura, anche se accede a una variabile esterna b :

function makeF(a) {
  var b = 2 * a;
  return function (c) {
    return b + c;
  };
}
var f = makeF(3);

Un esempio di una variabile esterna che potrebbe essere letta e scritta senza trasformare una funzione impura sarebbe una cache. La cache non influisce sul risultato di una funzione, è solo un'ottimizzazione. Qui, la purezza dipende dalla prospettiva. Una funzione pura memorizzata / memorizzata nella cache potrebbe essere impura dal punto di vista di uno scrittore di compilatori perché accede alla cache come un effetto collaterale. Ma è puro dalla prospettiva di un utente della funzione - e possiamo ancora sostituire un'espressione di chiamata di funzione con il suo risultato.

    
risposta data 21.07.2018 - 16:37
fonte
3

Trasparenza referenziale significa che è possibile sostituire un'applicazione di funzione con il suo risultato (o più in generale, un'espressione con la sua valutazione) ovunque e / o ovunque nel programma, senza modificarne il risultato.

Ecco un esempio di un programma con una funzione che legge solo ma non modifica una variabile globale:

let global = 0;

function foo(i) {
  return i + global;
}

const one = foo(1);
// foo(1) == 1

global = 100;

const two = foo(1);
// I should be able to replace this with const two = 1, since foo(1) was 1 above

console.log(two);
// 101

Questo stampa 101 .

Se foo fosse referenzialmente trasparente, dovrei essere in grado di sostituire qualsiasi occorrenza di foo(1) con 1 . E viceversa, dovrei essere in grado di sostituire qualsiasi occorrenza di 1 con foo(1) .

Proviamo:

let global = 0;

function foo(i) {
  return i + global;
}

const one = foo(1);

global = 100;

const two = 1;

console.log(two);
// 1
// Oops!

Come puoi vedere, la sostituzione di foo(1) con il suo risultato modifica il significato del programma. Ergo, foo non è referenzialmente trasparente.

C'è un'altra lezione importante qui: se global fosse una costante anziché una variabile, allora foo sarebbe referenzialmente trasparente. foo non è referenzialmente trasparente a causa di un pezzo di codice completamente diverso da qualche altra parte. Gli effetti collaterali sono contagiosi e possono agire su grandi distanze!

    
risposta data 21.07.2018 - 16:28
fonte
0

Tendo a sì, perché chiamare la stessa funzione due volte (con gli stessi argomenti) può portare a risultati diversi. Si noti che, supponendo che la funzione sia altrimenti pura, può essere facilmente modificata per essere effettivamente pura passando il valore della variabile globale come argomento alla funzione.

    
risposta data 21.07.2018 - 16:24
fonte

Leggi altre domande sui tag