Quão perto estão as linguagens de programação comuns de não serem completas de Turing?

7

O termo "perfeição de Turing" foi discutido em várias das aulas de ciência da computação que eu participei. No entanto, nunca tive uma noção intuitiva do que a integridade de Turing realmente exige. Encontrei essa pergunta, mas as respostas são um pouco mais matemáticas do que o que estou procurando.

Pegue uma linguagem de programação comum, como C ++, Python, Java ou Lisp. A que distância essas línguas estão de Turing não estar completa? Essas linguagens possuem recursos elementares que, se removidos, tornariam a linguagem não Turing completa? Ou você poderia alterar uma propriedade do idioma (por exemplo, tornar algo aleatório) e, ao fazer isso, tornar o idioma não Turing completo?

haroba
fonte
11
Acho que as respostas para a pergunta que você vincula respondem a todas as suas perguntas.
Raphael
Discordo. Eles discutem os recursos mínimos exigidos de um idioma para que ele seja completo em Turing, mas não mencionam os idiomas da vida real.
haroba
As linguagens da vida real são, na maioria das vezes, offtopic aqui. Deve ser fácil comparar os recursos listados na minha resposta com qualquer idioma, por exemplo, a maioria das linguagens processuais / orientadas a objetos possuem whileloops.
Raphael
11
Observe que Turing Completeness é uma coisa comum. Você pode simular máquinas de Turing usando as ferramentas mais estranhas: bolas de bilhar , autômatos celulares , falhas de página da Intel e muito mais. Quase todo sistema interessante permite que Turing calcule completamente, eu sinto.
precisa saber é o seguinte

Respostas:

7

Linguagens de programação comuns são muito firmemente concluídas em Turing, se você tiver uma visão idealizada de onde os programas podem usar uma grande quantidade arbitrária de memória. Normalmente, não há um único recurso que você possa isolar sem o qual o idioma não seria completo em Turing.

Intuitivamente falando, a integridade de Turing requer duas coisas:

  • Uma maneira de os programas manipularem uma quantidade de memória que não depende apenas do tamanho da entrada. Qualquer forma de criação do objeto que pode construir objetos maiores de objetos menores é adequado: objetos, estruturas, pares, listas, malloc, new, etc. Mesmo alocação baseada em pilha é suficiente, desde que haja uma forma de objetos de acesso a qualquer distância do topo da pilha (apenas com alocação baseada em pilha e apenas acesso ao topo da pilha, você obtém apenas um autômato de empilhamento). Muitas formas mais fracas de manipulação de dados também são adequadas: por exemplo, em uma linguagem como Lisp ou Python, onde os números inteiros não têm tamanho limitado, as operações inteiras básicas por si só são suficientes para a integridade de Turing.
  • Uma maneira de os programas continuarem em execução ou pararem com base em alguma parte dos dados. Enquanto loops, recursão mais alguma forma de condicional (por exemplo, ifou case/ switch) e gotomais alguma forma de condicional são as três formas mais comuns, mas existem outras.

Penso que a melhor maneira de entender o que torna uma linguagem completa em Turing é observar exemplos de linguagens poderosas, mas não completas em Turing. Vou dar dois exemplos que ilustram as duas famílias principais desses idiomas (exceto os que operam na memória limitada).

Considere uma linguagem imperativa com operações e matrizes inteiras, mas apenas para loops ( for i = 1 to nonde inão pode ser modificado durante o loop), não para loops arbitrários (while) e sem recursão. BlooP e versões anteriores do FORTRAN são exemplos. Nesse idioma, você só pode expressar funções recursivas primitivas - funções em que a quantidade de computação é limitada no tamanho da entrada. O idioma não está completo em Turing - não pode expressar funções recursivas arbitrárias - devido ao limite no tempo de computação.

Uma linguagem funcional pode ser tornada não completa de Turing, restringindo a recursão por meio de um sistema de tipos que restringe todas as funções a serem encerradas. Se o sistema de tipos for decidível (ou seja, se for decidível se o programa está bem digitado), esse idioma não poderá ser concluído por Turing (porque o problema de parada é indecidível). Idiomas usados ​​para a prova de teoremas, como Coq e Agda , são desse tipo.

Veja também O que Idris não pode fazer renunciando à totalidade de Turing?


Em uma nota lateral, os provadores de teoremas exigem que o usuário insira provas de término (ou seja, eles não os encontram). Assim, você poderia fazer um teste de teoremas com um sistema de tipos indecidíveis: se você receber uma prova correta, estará feliz, caso contrário, desistirá após um tempo. Mas não seria fácil de usar. A maioria dos provadores de teoremas tem um sistema de tipos decidível: você digita um termo e ele é aceito ou você recebe um erro de tipo de volta. O que os provadores de teoremas não têm é uma inferência de tipo decidível : se você digitar um termo com informações de tipo parcial e for rejeitado, não saberá se é porque o termo não pode ser digitado ou porque o mecanismo de inferência não era suficientemente inteligente.

Gilles 'SO- parar de ser mau'
fonte