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 ref
tipo de essência genérico . Portanto, uma int
variável é imutável e uma ref int
variável é um contêiner mutável para int
s. Basicamente, variáveis são variáveis reais no sentido matemático (um valor desconhecido, mas fixo) ref
es 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 const
não optar por sair dele. Mas quando você se esquece de const
algo e depois o corrige, você acabará na situação "const envenenamento" mencionada na resposta do @ RobY, onde a const
mudança ocorrerá em cascata no código. Se const
fosse o padrão, você não se aplicaria const
retroativamente. Além disso, ter que adicionar em const
qualquer 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 const
não se trata diretamente da imutabilidade dos dados; const
codifica 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 stdin
considerar Hello, world!
, na primeira vez que você tentar recuperar o valor do primeiro nó, ele lerá um char
e retornará H
. Depois disso, ele continuará retornando H
sem mais chamadas para ler a char
. Da mesma forma, o segundo nó leria um char
destdin
a primeira vez que você tenta recuperar seu valor, dessa vez retornando e
e 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
const
mesmo que o fluxo se comporte como um valor imutável. Agora imagine que há uma Stream
interface com const
métodos, e todas as suas funções esperam const Streams
. Você CharStream
não pode implementar a interface!
( EDIT 2: Aparentemente, existe uma palavra-chave C ++ chamada mutable
que nos permite trapacear e criarCharStream
const
. No entanto, essa brecha destrói const
as garantias - agora você realmente não pode ter certeza de que algo não sofrerá alterações por meio de seus const
mé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. const
ness faz parte da assinatura de uma função, portanto você não seria capaz de passar não- const
funções como argumentos para funções que esperam const
funções. Aplicar cegamente const
aqui levaria a uma perda de generalidade.
Finalmente, manipular um const
objeto não garante que ele não esteja alterando algum estado externo (estático ou global) pelas suas costas, portanto const
as 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.