Le funzioni referenzialmente trasparenti hanno effetti collaterali?

5

Leggo ovunque che la trasparenza referenziale e gli effetti collaterali si escludono a vicenda per tutte le funzioni, tuttavia, per quanto riguarda il caso in cui una funzione modifica uno stato che non ha alcun effetto sui suoi output. Ad esempio:

global_variable = 0

def foo(a,b):
    global_variable += 2
    return a + b

# Other code ...

Ora, se chiami questa funzione, sembra che si adatti alla definizione standard di trasparenza referenziale mentre cambia anche stato e quindi ha effetti collaterali.

Con questo in mente, mi chiedo, frainteso la trasparenza referenziale o persino l'idea di un effetto collaterale? È corretto dire che la funzione foo è sia referenzialmente trasparente che ha effetti collaterali?

In una certa misura, ritengo che sia controproducente estendere la definizione di trasparenza referenziale alla condizione che gli effetti collaterali senza alcun effetto sul valore di ritorno di una funzione escludano ancora le funzioni dall'essere considerate referenzialmente trasparenti.

    
posta swanyboy 30.03.2014 - 21:33
fonte

2 risposte

15

Trasparenza referenziale significa che è possibile sostituire un'espressione con il risultato di valutare quell'espressione ovunque nel programma senza modificare il risultato del programma.

Quindi, prendi il seguente programma:

a = foo(1, 2) + foo(1, 2)
b = a + global_variable

La trasparenza referenziale dice che posso sostituire ogni ricorrenza di foo(1, 2) con il risultato della valutazione di foo(1, 2) (cioè 3 ) senza cambiare il significato del programma. Quindi, questo programma deve avere lo stesso esatto risultato del programma precedente:

a = 3 + 3
b = a + global_variable

Ma non è così. Il primo programma ha a = 6 e b = 10 il secondo programma ha a = b = 6 . Pertanto, foo non è Referentially Transparent.

In effetti, possiamo semplificare ulteriormente il programma, volevo solo dimostrare cosa "ovunque nel programma":

foo(1, 2)

deve essere uguale a

3

ma i valori di global_variable in entrambi i programmi sono diversi.

Si noti che un'espressione complessa può essere Referentially Transparent se vista come una scatola nera anche se le sue parti costitutive non lo sono.

Ad esempio:

def foo(a, b)
  static mutable_cache
  if not mutable_cache.has_key?([a, b])
    mutable_cache[[a, b]] = a + b
  end
  return mutable_cache[[a, b]]
end

foo utilizza una struttura dati mutabile per memorizzare i risultati dell'operazione incredibilmente costosa di aggiungere due interi. Anche se chiaramente non è RT, la funzione vista come una casella nera è : posso sostituire foo(1, 2) con 3 ovunque senza modificare il risultato del programma nel suo complesso. Gli effetti collaterali sono contenuti entro foo . Talvolta viene chiamato esternamente puro . Questo è comune in Scala, per esempio. La libreria standard favorisce interfacce referentially trasparenti, ma a volte l'implementazione (nascosta) utilizza la mutazione sotto il cofano.

    
risposta data 30.03.2014 - 21:52
fonte
1

Nel tuo esempio, la variabile global_variable è non referenzialmente trasparente, perché il suo valore è mutato - non possiamo scambiare arbitrariamente global_variable con 0 nel programma.

Sebbene la funzione foo abbia effetti collaterali, si potrebbe anche sostenere che si tratta di una funzione pura perché il valore di ritorno dipende esclusivamente dagli argomenti della funzione. Tuttavia, questa è non una contraddizione: foo non è una funzione in senso matematico, ma più simile a una procedura (che viene eseguita esclusivamente per effetti collaterali).

Quindi la domanda è cosa esattamente intendi per "trasparenza referenziale":

  • Un nome è intercambiabile con la definizione a cui è stato associato:

    Quindi sì, foo sarebbe trasparente in modo referenziale perché la funzione di inlining non cambierà il comportamento del programma.

  • Un'espressione è intercambiabile con il valore di tale espressione:

    Quindi no, perché la sostituzione di foo(x, y) con x + y non mantiene tutti gli effetti collaterali della procedura foo .

risposta data 30.03.2014 - 21:55
fonte

Leggi altre domande sui tag