Hai già detto nella tua domanda come puoi capire se il tuo programma è referenzialmente trasparente o meno: se puoi sostituire un'espressione con il suo valore, senza cambiare il significato del programma, è referenzialmente trasparente. Se non puoi farlo, non lo è.
Quindi proviamo a sostituire alcune espressioni con i loro valori!
nel tuo metodo summation
, nella prima riga, imposta total
su 0
. Quindi, se il tuo programma è referenzialmente trasparente, dovremmo essere in grado di sostituire qualsiasi occorrenza di total
con 0
. Ad esempio, in questo modo:
def summation(n, term):
total, k = 0, 1
while k <= n:
total, k = 0 + term(k), k + 1
return total
o in questo modo:
def summation(n, term):
total, k = 0, 1
while k <= n:
total, k = total + term(k), k + 1
return 0
Lo stesso vale per k
:
def summation(n, term):
total, k = 0, 1
while k <= n:
total, k = total + term(k), 1 + 1
return total
o qui:
def summation(n, term):
total, k = 0, 1
while k <= n:
total, k = total + term(1), k + 1
return total
o qui:
def summation(n, term):
total, k = 0, 1
while 1 <= n:
total, k = total + term(k), k + 1
return total
mettiamole insieme:
def summation(n, term):
total, k = 0, 1
while 1 <= n:
total, k = 0 + term(1), 1 + 1
return 0
Inoltre, qual è il valore di ritorno del ciclo while
? Il ciclo while
non ha ha un valore di ritorno, non restituisce nulla. Secondo le regole della trasparenza referenziale, dovremmo essere in grado di sostituire qualsiasi espressione con il suo valore di ritorno senza cambiare il significato del programma, ergo, dovremmo essere in grado di sostituire l'intero ciclo while
senza niente:
def summation(n, term):
total, k = 0, 1
return total
Di nuovo, se il tuo programma fosse referenzialmente trasparente, questo non dovrebbe cambiare il risultato.
Si noti che un ciclo semplicemente non può essere referenzialmente trasparente. La trasparenza referenziale può anche essere interpretata come "se faccio la stessa cosa, succede la stessa cosa". Ma in un ciclo, facciamo la stessa cosa più e più volte, tuttavia, ci aspettiamo che qualcosa di diverso accada ogni volta, o almeno una volta: il ciclo si ferma.
Ecco un esempio di come implementare summation
senza interrompere la trasparenza referenziale:
def summation(n, term):
if n == 0:
return term(n)
else:
return term(n) + summation(n - 1, term)
Ed ecco un'implementazione in un modo ricorsivo di coda usando lo standard "introdurre un accumulatore":
def summation(n, term):
def summation_rec(n, total):
if n == 0:
return total
else:
return summation_rec(n-1, total + term(n))
return summation_rec(n, 0)
(Sfortunatamente, ciò non aiuta, dal momento che Python non implementa le opportune chiamate di coda, nemmeno la corretta ricorsione di coda. Quindi, questo continuerà a far esplodere lo stack per un% maggiore din
. Ma in una lingua con la corretta implementazione di ricorsione di coda o anche chiamate di coda appropriate, questo verrà eseguito nello spazio di stack O (1).)