Precisamos falar sobre parênteses (2020)

As discussões sobre o quanto as linguagens de programação devem depender de parênteses e da precedência de operadores revelam compromissos profundos entre legibilidade, familiaridade e poder de metaprogramação. Alguns participantes defendem pouca precedência e mais agrupamento explícito (ou até sintaxe no estilo RPN), enquanto outros defendem regras convencionais semelhantes às da matemática e os S-expressions totalmente parentetizados de Lisp, especialmente quando combinados com boa indentação e suporte do editor. A troca também aborda como a sintaxe molda ferramentas, escopo e a facilidade de transformar código, e por que — apesar das vantagens de macros e de “código como dados” em Lisp — a maioria das linguagens mainstream continua a favorecer formas sintáticas mais variadas e menos uniformes.

Precedência de operadores vs. parênteses obrigatórios

  • Um grupo argumenta que a precedência de operadores é um erro de projeto; expressões com operadores mistos como 1 + 1 * 2 ou a | b || c >> d & e * f deveriam ser erros de sintaxe, a menos que estejam explicitamente entre parênteses.
  • Outros discordam fortemente, citando a simplicidade da notação, os paralelos com a álgebra e o peso de código excessivamente parentetizado.
  • Compromisso proposto: uma ordem parcial de precedência. Combinações comuns (por exemplo, * sobre +) são permitidas; misturas incomuns (por exemplo, * com &) são rejeitadas como “precedência ambígua”.
  • O debate se estende à matemática: alguns dizem que a precedência é inerente (“ordem das operações”); outros insistem que ela é puramente uma propriedade da notação, muitas vezes expressa visualmente por frações, expoentes, radicais etc.

Parênteses em Lisp, legibilidade e ferramentas

  • Muitos observam que, em Lisp, indentação automática, edição estrutural e realce de parênteses são considerados essenciais; eles revelam rapidamente parênteses ausentes ou deslocados.
  • Alguns argumentam que o único tipo de parêntese de Lisp prejudica a legibilidade e sugerem vários tipos de colchetes para diferentes papéis sintáticos, ou até colchetes intercambiáveis apenas para agrupamento visual.
  • Contra-argumento: usuários experientes de Lisp em geral “enxergam formas”, não parênteses, e confiam em padrões que começam com símbolos em vez de contar colchetes.
  • A edição estrutural é elogiada: delimitadores explícitos mais autoformatação funcionam como uma “contabilidade de partidas dobradas” para a estrutura do código.

Estilo de sintaxe, espaços em branco e escopo

  • Alguns celebram linguagens que eliminam parênteses desnecessários em construções como condições de if (Go, Scala 3).
  • Há desacordo sobre espaços em branco significativos: alguns preferem delimitadores explícitos; outros acham a sintaxe centrada em indentação mais legível.
  • Discussão sobre escopo: blocos lexicais apertados ({} ou formas let) podem reduzir variáveis vivas, mas nem todos os tempos de vida podem ser minimizados; exemplos em C, Rust (tempos de vida não lexicais) e código funcional/mônico ilustram os compromissos.

Código-como-dado e metaprogramação em Lisp

  • Vários comentários enfatizam que os parênteses de Lisp representam listas; programas são listas, e citar transforma código em dado.
  • Operações simples em listas podem transformar código (por exemplo, substituir todos os * por + e então eval), sustentando macros poderosas e sintaxes específicas de domínio.
  • Entusiastas veem isso como a principal força de Lisp; céticos respondem que outras linguagens agora oferecem metaprogramação forte com sintaxe menos visualmente repetitiva e questionam se parênteses são um bom compromisso ergonômico.