Observe se isso se qualifica para você, mas em idiomas funcionais como o ML padrão tudo é imutável por padrão. A mutação é suportada por meio de um reftipo de essência genérico . Portanto, uma intvariável é imutável e uma ref intvariável é um contêiner mutável para ints. Basicamente, variáveis são variáveis reais no sentido matemático (um valor desconhecido, mas fixo) refes são "variáveis" no sentido imperativo da programação - uma célula de memória que pode ser escrita e lida. (Gosto de chamá-los de atribuíveis .)
Eu acho que o problema consté duplo. Primeiro, o C ++ não possui coleta de lixo, o que é necessário para ter estruturas de dados persistentes não triviais . const deve ser profundo para fazer algum sentido, mas ter valores totalmente imutáveis em C ++ é impraticável.
Segundo, em C ++ você precisa optar por constnão optar por sair dele. Mas quando você se esquece de constalgo e depois o corrige, você acabará na situação "const envenenamento" mencionada na resposta do @ RobY, onde a constmudança ocorrerá em cascata no código. Se constfosse o padrão, você não se aplicaria constretroativamente. Além disso, ter que adicionar em constqualquer lugar adiciona muito ruído ao código.
Eu suspeito que as principais linguagens que se seguiram (por exemplo, Java) foram fortemente moldadas pelo sucesso e pela maneira de pensar de C e C ++. Caso em questão, mesmo com a coleta de lixo, a maioria das APIs de coleta de idiomas assume estruturas de dados mutáveis. O fato de tudo ser mutável e a imutabilidade ser visto como um caso de canto fala muito sobre a mentalidade imperativa por trás das línguas populares.
EDIT : Depois de refletir sobre o comentário de greenoldman, percebi que constnão se trata diretamente da imutabilidade dos dados; constcodifica no tipo do método se tem efeitos colaterais na instância.
É possível usar a mutação para obter um comportamento referencialmente transparente . Suponha que você tenha uma função que, quando chamada, retorne sucessivamente valores diferentes - por exemplo, uma função que lê um único caractere stdin. Poderíamos usar cache / memorizar os resultados dessa função para produzir um fluxo de valores referencialmente transparente. O fluxo seria uma lista vinculada cujos nós chamarão a função na primeira vez que você tentar recuperar seu valor, mas depois armazenará em cache o resultado. Portanto, se stdinconsiderar Hello, world!, na primeira vez que você tentar recuperar o valor do primeiro nó, ele lerá um chare retornará H. Depois disso, ele continuará retornando Hsem mais chamadas para ler a char. Da mesma forma, o segundo nó leria um chardestdina primeira vez que você tenta recuperar seu valor, dessa vez retornando ee armazenando em cache esse resultado.
O interessante aqui é que você transformou um processo inerentemente estável em um objeto aparentemente sem estado. No entanto, foi necessário alterar o estado interno do objeto (armazenando os resultados em cache) para conseguir isso - a mutação foi um efeito benigno . É impossível fazer o nosso, CharStream constmesmo que o fluxo se comporte como um valor imutável. Agora imagine que há uma Streaminterface com constmétodos, e todas as suas funções esperam const Streams. Você CharStreamnão pode implementar a interface!
( EDIT 2: Aparentemente, existe uma palavra-chave C ++ chamada mutableque nos permite trapacear e criarCharStream const . No entanto, essa brecha destrói constas garantias - agora você realmente não pode ter certeza de que algo não sofrerá alterações por meio de seus constmétodos. Suponho que não seja isso. ruim, pois você deve solicitar explicitamente a brecha, mas ainda depende totalmente do sistema de honra.)
Em segundo lugar, suponha que você tenha funções de alta ordem - ou seja, você pode passar funções como argumentos para outras funções. constness faz parte da assinatura de uma função, portanto você não seria capaz de passar não- constfunções como argumentos para funções que esperam constfunções. Aplicar cegamente constaqui levaria a uma perda de generalidade.
Finalmente, manipular um constobjeto não garante que ele não esteja alterando algum estado externo (estático ou global) pelas suas costas, portanto constas garantias não são tão fortes quanto parecem inicialmente.
Não está claro para mim que codificar a presença ou ausência de efeitos colaterais no sistema de tipos é universalmente uma coisa boa.