Nella programmazione funzionale poiché quasi tutte le strutture dati sono immutabili, quando lo stato deve cambiare viene creata una nuova struttura. Questo significa molto più utilizzo della memoria?
Dipende dalla struttura dei dati, dalle modifiche esatte eseguite e, in alcuni casi, dall'ottimizzatore. Ad esempio, consideriamo di anteporre a un elenco:
list2 = prepend(42, list1) // list2 is now a list that contains 42 followed
// by the elements of list1. list1 is unchanged
Qui il requisito di memoria aggiuntiva è costante, così come il costo di runtime della chiamata prepend
. Perché? Perché prepend
semplicemente crea una nuova cellula che ha 42
come testa e list1
coda. Non è necessario copiare o iterare in altro modo list2
per raggiungere questo obiettivo. Cioè, ad eccezione della memoria richiesta per l'archiviazione 42
, list2
riutilizza la stessa memoria utilizzata da list1
. Poiché entrambi gli elenchi sono immutabili, questa condivisione è perfettamente sicura.
Allo stesso modo, quando si lavora con strutture ad albero bilanciate, la maggior parte delle operazioni richiede solo una quantità logaritmica di spazio aggiuntivo perché è possibile condividere qualsiasi cosa, tranne un percorso dell'albero.
Per gli array la situazione è leggermente diversa. Ecco perché, in molte lingue FP, le matrici non sono quelle comunemente usate. Tuttavia, se fai qualcosa di simile arr2 = map(f, arr1)
e arr1
non viene più utilizzato dopo questa riga, un ottimizzatore intelligente può effettivamente creare codice che muta arr1
invece di creare un nuovo array (senza influire sul comportamento del programma). In tal caso, lo spettacolo sarà ovviamente come in un linguaggio imperativo.