Potrei avere una visione troppo bassa di questo e probabilmente perché sto usando C e C ++ che non rendono esattamente così semplice rendere tutto immutabile, ma vedo i tipi di dati immutabili come un ottimizzazione dettagli per scrivere funzioni più efficienti privo di effetti collaterali ed essere in grado di fornire facilmente funzionalità come i sistemi di annullamento e l'editing non distruttivo.
Ad esempio, questo potrebbe essere estremamente costoso:
/// @return A new mesh whose vertices have been transformed
/// by the specified transformation matrix.
Mesh transform(Mesh mesh, Matrix4f matrix);
... se Mesh
non è progettato per essere una struttura di dati persistente ed era, invece, un tipo di dati che richiedeva di copiarlo completamente (che potrebbe estendersi in gigabyte in alcuni scenari) anche se tutto ciò che stiamo andando sta facendo sta cambiando una parte di esso (come nello scenario precedente in cui modifichiamo solo le posizioni dei vertici).
Ecco quindi quando raggiungo l'immutabilità e progetto la struttura dei dati per consentire che porzioni non modificate siano copiate e conteggio dei riferimenti superficiali, per consentire alla funzione sopra riportata di essere ragionevolmente efficiente senza dover copiare in profondità intere maglie mentre si è ancora in grado scrivere la funzione per essere priva di effetti collaterali che semplifica drasticamente la sicurezza del thread, la sicurezza delle eccezioni, la possibilità di annullare l'operazione, applicarla in modo non distruttivo, ecc.
Nel mio caso è troppo costoso (almeno dal punto di vista della produttività) per rendere tutto immutabile, quindi lo salvo per le classi che sono troppo costose da copiare in profondità. Queste classi sono solitamente strutture di dati pesanti come maglie e immagini e generalmente uso un'interfaccia mutevole per esprimere le modifiche ad esse attraverso un oggetto "costruttore" per ottenere una nuova copia immutabile. E non lo sto facendo così tanto per cercare di ottenere garanzie immutabili al livello centrale della classe tanto quanto aiutarmi ad usare la classe in funzioni che possono essere prive di effetti collaterali. Il mio desiderio di rendere Mesh
sopra immutabile non è direttamente quello di rendere le mesh immutabili, ma di consentire facilmente la scrittura di funzioni prive di effetti collaterali che inseriscono una mesh e ne generano una nuova senza pagare una memoria enorme e costi computazionali in cambio.
Di conseguenza ho solo 4 tipi di dati immutabili nella mia intera base di codice, e sono tutte strutture di dati pesanti, ma li uso pesantemente per aiutarmi a scrivere funzioni prive di effetti collaterali. Questa risposta potrebbe essere applicabile se, come me, stai lavorando in una lingua che non rende così facile rendere tutto immutabile. In tal caso, è possibile spostare l'attenzione verso il fatto che la maggior parte delle funzioni eviti gli effetti collaterali, a quel punto si potrebbe voler rendere selezionabili strutture dati immutabili, come i dettagli di ottimizzazione per evitare le costose copie complete. Nel frattempo quando ho una funzione come questa:
/// @return The v1 * v2.
Vector3f vec_mul(Vector3f v1, Vector3f v2);
... quindi non ho alcuna tentazione di rendere i vettori immutabili dal momento che sono abbastanza economici da essere copiati per intero. Non c'è alcun vantaggio in termini di prestazioni da ottenere qui trasformando i vettori in strutture immutabili che possono copiare in profondità parti non modificate. Tali costi supererebbero il costo della semplice copia dell'intero vettore.