Mutabilidade

D é uma linguagem estaticamente tipada: depois que uma variável é declarada, seu tipo não pode ser alterado daquele ponto em diante. Isso permite que o que o compilador evite bugs desde o início e imponha restrições em tempo de compilação. Uma boa segurança de tipo oferece o suporte necessário para tornar os programas grandes mais seguros e mais fáceis de manter.

Há vários qualificadores de tipo em D, mas os mais comumente usados são const e immutable.

immutable

Além de um sistema de tipos estáticos, o D fornece qualificadores de tipos (às vezes também chamados de "construtores de tipos") que impõem restrições adicionais a determinados objetos. Por exemplo, um objeto immutable só pode ser inicializado uma vez e depois disso, não pode ser alterado.

immutable int err = 5;
// ou: immutable err = 5 e int será inferido.
err = 5; // não compila

Os objetos imutáveis podem, portanto, ser compartilhados com segurança entre diferentes threads sem sincronização, pois, por definição, eles nunca mudam. Isso também implica que os objetos os objetos immutable podem ser armazenados em cache perfeitamente.

const

Os objetos não podem ser modificados por meio de uma referência const. Uma referência mutável para o mesmo objeto ainda pode modificá-lo. Um ponteiro const pode ser criado a partir de um objeto mutável ou objeto immutable. É comum que as APIs aceitem argumentos const para garantir que não modifiquem a entrada, pois isso permite que a mesma função processe dados mutáveis e imutáveis.

void foo(const char[] s)
{
    // se não for comentada, a próxima linha
    // resultará em erro (não é possível modificar const):
    // s[0] = 'x';

    import std.stdio : writeln;
    writeln(s);
}

// graças ao `const`, ambas as chamadas serão compiladas:
foo("abcd"); // string é um array imutável
foo("abcd".dup); // .dup returna uma cópia mutável

Transitividade

Tanto immutable quanto const são qualificadores de tipo transitivos, garantindo assim que, uma vez que const seja aplicado a um tipo, ele se aplica recursivamente a cada subcomponente desse tipo.

immutable int* p = new int;
p = null; // erro
*p = 5; // erro

O tipo de elemento de um ponteiro (ou array) pode ser qualificado separadamente:

immutable p = new int; // immutable(int*)
immutable(int)* q = p; // OK, ponteiro mutável
q = null; // OK
*q = 5; // erro

O tipo [string] (basics/alias-strings) é definido como immutable(char)[]:

string s = "hi";
s ~= " world"; // OK, acrescenta novos caracteres
s[0] = 'c'; // erro, não é possível alterar dados existentes

Maiores detalhes

Referências básicas

Referências avançadas

rdmd playground.d