This is not explained any further. I try to find an explanation.
È qualcosa che è intrinseco a molti di noi che hanno eseguito il debug di codebase enormi, ma per poterlo apprezzare devi affrontare una scala abbastanza grande a livello di supervisore. È come capire l'importanza di essere in posizione in Poker. Inizialmente non sembra un vantaggio così utile andare alla fine di ogni turno fino a quando non registri una storia di mani di un milione di mani e ti rendi conto che hai vinto così tanto denaro in posizione che fuori.
Detto questo, non sono d'accordo con l'idea che il passaggio a una variabile locale sia un effetto collaterale. Dal mio punto di vista, una funzione non causa effetti collaterali se non modifica nulla al di fuori del suo ambito, che qualsiasi cosa tocchi e manomette non influirà su qualcosa sotto lo stack di chiamate o su qualsiasi memoria o risorsa che la funzione non ha acquisito .
In generale, la cosa più difficile da ragionare in una base di codice complessa e su larga scala che non ha la procedura di test più perfetta che si possa immaginare è la gestione persistente dello stato, come tutte le modifiche agli oggetti granulari in un mondo di videogiochi mentre guadagni attraverso decine di migliaia di funzioni mentre cercavo di restringere una lista infinita di sospetti che in realtà causava la violazione di un invariante a livello di sistema ("questo non dovrebbe mai accadere, chi lo ha fatto?"). Se nulla viene mai modificato al di fuori di una funzione, allora non può causare un malfunzionamento centrale.
Ovviamente non è possibile farlo in tutti i casi. Qualsiasi applicazione che aggiorna un database memorizzato su un altro computer è, per sua natura, progettata per causare effetti collaterali, nonché qualsiasi applicazione progettata per caricare e scrivere file. Ma c'è molto di più che possiamo fare senza effetti collaterali in molte funzioni e molti programmi se, ad esempio, disponessimo di una ricca libreria di strutture dati immutabili e avessimo adottato ulteriormente questa mentalità.
Stranamente John Carmack è saltato sul LISP e sul carrozzone dell'immutabilità nonostante abbia iniziato nei giorni della codifica C più sintonizzata. Mi sono trovato a fare una cosa simile, anche se uso ancora molto C. Tale è la natura dei pragmatici, penso, che hanno trascorso anni di debugging e tentando di ragionare su sistemi complessi e su larga scala nel loro insieme da un livello di sovrintendente. Persino quelli che sono sorprendentemente robusti e privi di una grande quantità di bug possono ancora lasciarti con una sensazione inquietante che qualcosa di sbagliato è in agguato dietro l'angolo se c'è un sacco di complessi stati persistenti che vengono modificati tra il più complesso grafico interconnesso delle chiamate di funzione tra i milioni di righe di codice. Anche se ogni singola interfaccia viene testata con un test unitario e tutto passa, c'è anche la sensazione spiacevole di ciò che potrebbe accadere agli stati centrali con un caso di input non previsto con tutte le innumerevoli chiamate di funzioni interdipendenti tra interfacce se la logica dell'applicazione ruota attorno al lato a cascata effetti agli stati più centrali e persistenti.
In pratica, trovo spesso che la programmazione funzionale renda più difficile comprendere una funzione. Gira ancora il mio cervello in colpi di scena e nodi, specialmente con una complessa logica ricorsiva. Ma tutto il sovraccarico intellettuale associato a capire un paio di funzioni scritte in un linguaggio funzionale è sminuito da quello di un sistema complesso con stati persistenti che vengono cambiati attraverso decine di migliaia di funzioni, dove ogni funzione che causa effetti collaterali si somma al totale complessità del ragionamento sulla correttezza dell'intero sistema nel suo complesso.
Nota che non hai bisogno di un linguaggio puramente funzionale per far sì che le funzioni evitino gli effetti collaterali. Gli stati locali modificati in una funzione non contano come effetto collaterale, come una variabile del contatore del ciclo for
locale a una funzione non conta come un effetto collaterale. Scrivo anche codice C al giorno d'oggi con l'obiettivo di evitare gli effetti collaterali quando possibile e ho escogitato una libreria di strutture di dati immutabili e thread-safe che possono essere parzialmente modificate mentre il resto dei dati è poco profondo, e mi ha aiutato ottimo per ragionare sulla correttezza del mio sistema. Sono strongmente in disaccordo con l'autore in questo senso. Almeno in C e C ++ in software mission-critical, una funzione può documentare come senza effetti collaterali se non tocca nulla che possa influenzare il mondo al di fuori della funzione.