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.)