Ultimamente, fico cada vez mais frustrado que, nas linguagens de programação mais modernas com as quais trabalhei (C / C ++, C #, F #, Ruby, Python, JS e mais), há muito pouco, se houver, suporte à linguagem para determinar o que uma sub-rotina realmente funciona.
Considere o seguinte pseudocódigo simples:
var x = DoSomethingWith(y);
Como determino o que a chamada para DoSomethingWith (y) realmente fará? Será que vai mutação y , ou vai retornar uma cópia de y ? Depende do estado global ou local, ou depende apenas de y ? Mudará o estado global ou local? Como o fechamento afeta o resultado da chamada?
Em todos os idiomas que encontrei, quase nenhuma dessas perguntas pode ser respondida apenas com a assinatura da sub-rotina, e quase nunca há suporte em tempo de compilação ou em tempo de execução. Normalmente, a única maneira é confiar no autor da API e torcer para que a documentação e / ou convenções de nomenclatura revelem o que a sub-rotina realmente fará.
Minha pergunta é a seguinte: Existe alguma linguagem hoje que faz distinções simbólicas entre esses tipos de cenários e coloca restrições em tempo de compilação em qual código você pode realmente escrever?
(É claro que há algum suporte para isso na maioria das linguagens modernas, como diferentes níveis de escopo e fechamento, a separação entre código estático e de instância, funções lambda etc.). Mas, com muita frequência, elas parecem entrar em conflito entre si. Por exemplo, uma função lambda normalmente é puramente funcional e simplesmente retorna um valor com base nos parâmetros de entrada ou altera os parâmetros de entrada de alguma maneira, mas geralmente é possível acessar variáveis estáticas de uma função lambda, que por sua vez pode dar acesso a variáveis de instância e depois tudo se separa.)
fonte
Respostas:
Sim, você quer olhar para Haskell. Faz exatamente o que você quer. Todas as funções são puras por padrão e só podem mudar de estado usando Mônadas. Também Haskell tem fortes garantias estáticas sobre todos os tipos de coisas http://learnyouahaskell.com/
fonte
C e C ++ têm suporte muito limitado para pelo menos parte do problema por meio da
const
palavra - chave; embora isso por si só não controle a pureza, ele pode ser usado (especialmente em C ++) para informar ao compilador que uma estrutura de dados específica não deve ser modificada por meio de um determinado ponteiro. Alguns compiladores (por exemplo, gcc) também fornecem um atributo 'puro' como uma extensão de idioma para impor totalmente a pureza. (Veja esta pergunta para detalhes).A linguagem de programação D tem suporte para declarar explicitamente a pureza das funções, e os compiladores verificarão e reforçarão a pureza (ou seja, tentar chamar uma função não pura de dentro de uma função pura gera um erro do compilador).
Haskell é completamente puro, ou seja, a própria linguagem não pode expressar funções impuras, e não há conceito de "rotina". Tudo o que não pode ser resolvido usando apenas funções puras é terceirizado para o tempo de execução (impuro); um programa com efeitos colaterais é implementado construindo (usando construções exclusivamente puras) uma estrutura de dados lenta que descreve o comportamento do programa e entregando-a ao tempo de execução. A comunidade Haskell está experimentando ativamente um zoológico inteiro de linguagens de programação, algumas delas puras, outras com pureza explícita.
Pode haver mais, mas é com esses que eu estou familiarizado.
fonte
Felix tem três categorias, parece:
funções
procedimentos
geradores
fonte