Por que um idioma prefere o recuo do que marcadores explícitos para blocos?

11

Estou aprendendo Haskell e estava procurando uma ferramenta de indentação automática. Não olhei muito e aprendi que em Haskell (como em Python), o recuo significa um bloco. Como resultado, acho que é impossível criar uma ferramenta de formatação automática, tão forte quanto em outros idiomas da família C, que use marcadores explícitos, como {} (chaves) ou begin endpalavras-chave.

Não me importo com uma linguagem que imponha recuo para facilitar a leitura, mas não consigo entender os benefícios de impor recuo e ter algum marcador explícito, para que ferramentas automatizadas possam entender o que pertence a qual bloco.

Se a preferência de indentação marcando um bloco é para que o código pareça melhor, ainda não entendo a vantagem. Dado que guias e espaços são representados de maneira diferente em diferentes editores e fontes diferentes (fontes monoespaços, por exemplo, parecem mais organizadas), é inviável esperar que o programador apresente o código decentemente. Uma ferramenta que considere o editor de texto atual seria muito mais apropriada para formatar o código corretamente.

Por que um designer de linguagem escolheria recuo sobre marcadores de bloco explícitos?

Restabelecer Monica
fonte
8
Não é uma resposta, mas Haskell torna a sensibilidade ao espaço em branco muito mais opcional que o python. Você pode usar ponto-e-vírgula para a maioria das coisas e agrupar blocos em chaves, se desejar. let x =1; y = 2; z = 3é completamente válido, como é do { putStrLn $ show x; putStrLn $ show y; putStrLn $ show z; }. Aqueles não precisam estar na mesma linha.
KChaloux
8
"é impossível criar uma ferramenta de formatação automática" - na verdade, não há necessidade de uma ferramenta de formatação automática no Python por causa das regras de indentação.
Doc Brown
13
Hum, o aumento da indentação é um marcador de bloco explícito.
Karl Bielefeldt
3
@ K.Gkinis: A melhor fonte para as motivações exatas por trás de uma decisão de design de linguagem são os próprios designers de linguagem.
Robert Harvey
3
Esta questão não é realmente subjetiva. Ele pergunta por que alguns designers de linguagem escolheram uma certa sintaxe. Isso pode ser respondido. Se a pergunta perguntasse qual é a melhor sintaxe , seria subjetiva.
JacquesB

Respostas:

13

Guido Von Rossum

De uma entrevista com Guido Van Rossum , que pode ser vista em texto completo em books.google.com (grifo meu):

A escolha do recuo para agrupar não era um conceito novo em Python; Eu herdei isso da ABC , mas também ocorreu no occam, um idioma antigo. Não sei se os autores do ABC obtiveram a idéia do ocam, ou a inventaram independentemente, ou se havia um ancestral comum. Obviamente, eu poderia ter optado por não seguir o exemplo da ABC, como fiz em outras áreas (por exemplo, a ABC usava letras maiúsculas para palavras-chave e nomes de procedimentos, uma ideia que não copiei), mas eu gostei bastante do recurso pouco enquanto usava o ABC, pois parecia acabar com um certo tipo de debate inútil comum entre os usuários de C na época, sobre onde colocar os aparelhos .

Von Rossum foi fortemente inspirado pela ABC e, embora não tivesse que copiar tudo, o uso de indentação foi mantido, porque poderia ser benéfico para evitar guerras religiosas.

Eu também estava bem ciente de que código legível usa indentação voluntariamente de qualquer maneira para indicar o agrupamento, e encontrei bugs sutis no código em que o identificador discordava do agrupamento sintático usando chaves - o programador e quaisquer revisores supunham que o identificador correspondia ao agrupamento. e, portanto, não percebeu o bug. Novamente, uma longa sessão de depuração ensinou uma lição valiosa.

Rossum também testemunhou bugs devido à inconsistência entre o agrupamento e o recuo, e aparentemente apesar de confiar apenas no recuo para estruturar o código seria mais seguro contra erros de programação 1 .

Donald E. Knuth e Peter J. Landin

Na entrevista referenciada, Guido menciona a ideia de Don Knuth de usar indentação. Isso está detalhado em The Knuth Indentation Quote redescoberto , que cita a Programação Estruturada com Instruções Goto . Knuth também faz referência a As próximas 700 linguagens de programação de Peter John Landin (consulte a seção Discussão sobre recuo). Landin projetou o ISWIM, que se parece com o primeiro idioma com recuo em vez de blocos de início / fim. Esses documentos são mais sobre a viabilidade do uso de indentação para estruturar programas, em vez de argumentos reais a favor de fazê-lo.


1. Penso que este é de fato um argumento a favor de ter construções de agrupamento e formatação automática, a fim de capturar e recuperar de erros de programação, que estão prestes a acontecer. Se você estragar o seu recuo no Python, a pessoa que depura seu código terá que adivinhar o que está correto:

if (test(x)):
  foo(x)
  bar(x)

Deve barsempre ser chamado ou apenas se o teste de sucesso?

As construções de agrupamento adicionam um nível de redundância que ajuda a identificar um erro ao recuar automaticamente o código. Em C, o código equivalente pode ser recuado automaticamente da seguinte maneira:

if (test(x))
  foo(x);
bar(x);

Se eu pretendia barestar no mesmo nível que foo, então o recuo automático com base na estrutura do código permite ver que há algo errado que pode ser corrigido adicionando chaves entre fooe bar.

Em Python: Myths about Indentation , há um exemplo supostamente ruim de C:

/*  Warning:  bogus C code!  */

if (some condition)
        if (another condition)
                do_something(fancy);
else
        this_sucks(badluck);

É o mesmo caso acima, no Emacs, destaco todo o bloco / função, pressiono Tab e todo o código é reindentado. A discrepância entre a indentação humana e a estrutura do código indica que algo está errado (isso e o comentário anterior!).

Além disso, o código intermediário em que a indentação está desativada em C simplesmente não passa pela ramificação principal, todas as verificações de estilo existentes fazem o GCC / Jenkins gritar comigo. Recentemente, tive um problema semelhante ao descrito acima em Python, com uma declaração desativada por um nível de indentação. Às vezes, tenho um código em C que vai além de uma chave de fechamento, mas depois clico em Tab e o código é recuado "incorretamente": essa é mais uma chance de ver o bug.

coredump
fonte
3
"Para evitar guerras religiosas ..." Estou surpreso que a verdadeira razão seja tão trivial.
Robert Harvey
1
@RobertHarvey: A ênfase nessa frase é por coredump, não por van Rossum. Não é o principal motivo se você ler a citação de van Rossum no contexto.
JacquesB
@ JacquesB Por favor, diga-me que contexto está faltando na citação, para que eu possa editar a resposta.
Coredump
4
No entanto, não recebo comentários pessoais: se você estragar o recuo no Python, você tem um bug. Se você estragar o aparelho em C, você tem um bug. Se você usar o recuo automático, é exatamente o mesmo nos dois idiomas. E se você não usar o recuo automático, o bug pode ser oculto em C de uma maneira que não é possível no Python.
JacquesB
2
@ JacquesB porque digitar uma chave de fechamento é algo que você faz ativamente; não recuar o suficiente é algo que você pode esquecer de fazer. É claro que você pode esquecer de fechar uma chave na hora certa, mas precisará fazer isso eventualmente e ter outra chance de pensar sobre isso. Eu acho que python funciona bem para iniciantes porque força a atenção no recuo.
Marstato # 30/19
7

Isso é altamente subjetivo e causa de muitas guerras de chamas. Contudo:

Ter símbolos que delimitam blocos e recuo viola o princípio DRY , pois você expressa as mesmas informações de duas maneiras diferentes. A existência de ferramentas de indentação automatizadas é um sintoma dessa violação DRY: O fato de você poder gerar automaticamente o recuo mostra que são informações redundantes e significa que o recuo e os símbolos podem ficar fora de sincronia, o que leva a códigos enganosos.

As Perguntas frequentes sobre design e história do Python afirma isso muito claramente:

Por que o Python usa indentação para agrupar declarações?

Guido van Rossum acredita que o uso de indentação para agrupar é extremamente elegante e contribui muito para a clareza do programa Python comum. A maioria das pessoas aprende a amar esse recurso depois de um tempo.

Como não há colchetes de início / fim, não pode haver um desacordo entre o agrupamento percebido pelo analisador e pelo leitor humano.

É verdade que você não pode criar uma ferramenta de recuo automático para Python, mas isso é uma coisa boa: significa que você não possui redundâncias na sintaxe que precisa de ferramentas automatizadas para reconciliar.

As abas versus espaços é uma preocupação legítima no Python, e é recomendável nunca misturar abas e espaços (para indentação) na mesma base de código.

Python herdou a indentação significativa da linguagem predecessora ABC (agora obsoleta). O ABC é uma das poucas linguagens de programação que usaram testes de usabilidade para direcionar o design. Portanto, enquanto discussões sobre sintaxe geralmente se resumem a opiniões subjetivas e preferências pessoais, a escolha de um recuo significativo realmente tem uma base mais sólida.

JacquesB
fonte
6
A contabilidade de entrada dupla também viola o DRY. Às vezes, redundância é um recurso.
Coredump
3
@coredump: Verdade, mas é uma redundância deliberadamente projetada. A maioria das linguagens de programação, incluindo Python, contém redundâncias deliberadamente escolhidas - por exemplo, a passpalavra - chave que pode ser inferida automaticamente, mas exigir que seja explícita ajuda a descobrir erros. A redundância acidental de ter símbolos de início / fim (para o compilador) e indentação (para o leitor humano) parece causar mais erros do que os detectados. Pelo menos isso parece ser o ponto de vista de van Rossum.
JacquesB
@coredump - Agora eu sei por que não sou contador.
JeffO 17/03/16
3
@coredump Você também sente falta do COBOL PROCEDURE DIVISION.? Nunca sei onde é que os DATA DIVISIONfins e os procedimentos começam nessas novas linguagens.
msw
2
@coredump: "ver o recuo contradiz o que eu tinha em mente é suficiente para evitar erros" - exatamente.
JacquesB
2

Os designers de idiomas escolhem espaços em branco sintaticamente significativos porque acreditam (ou pelo menos pensam que seus usuários em potencial acreditam) que os pontos e vírgulas e os aparelhos acrescentam ruído ao ler código, prejudicando a produtividade. Outro motivo comum é que o estilo de codificação ruim / inconsistente prejudica a legibilidade - forçando um esquema de indentação comum, a linguagem tem melhor legibilidade em geral. Esse motivo posterior é menos importante agora que IDEs de formatação automática são mais comuns, mas ainda podem ser aplicados.

Telastyn
fonte
1
Eu posso ver por que alguém consideraria ponto e vírgula e barulho de chaves. Mas não é menos produtivo ter que digitar 4/8/12 vezes o espaço? E se você sente falta de uma (já que elas são invisíveis), está com problemas.
Reintegrar Monica
5
É por isso que você usa guias em vez de espaços ou um IDE que entende como converter guias em blocos de quatro espaços.
21416 Robert Harvey
@ K.Gkinis: Recuos não são invisíveis. Somente o espaço em branco no final das linhas é invisível, mas isso não é significativo em nenhum idioma. Somente se você misturar abas e espaços você terá problemas. Então não faça isso.
JacquesB
@ JacquesB: o problema com a visibilidade / invisibilidade da indentação é que, como humano, muitas vezes você não pode dizer a diferença entre espaços e uma guia, enquanto o computador pode e muitas vezes sabe. Portanto, enquanto o recuo é visível, a maneira como o computador interpreta o recuo pode ser diferente. Esse é o verdadeiro problema: quando o computador trata os caracteres invisíveis de maneira diferente dos humanos. Os seres humanos medem o recuo como a distância na tela, os computadores podem medi-lo como um número literal de caracteres. essa é a parte invisível.
Bryan Oakley
@BryanOakley: Sim, é por isso que você não deve misturar guias e espaços no recuo.
JacquesB