Uma das razões pelas quais as linguagens baseadas em Algol incentivam os chavetas em sua própria linha é incentivar a adição de mais linhas entre os chaveadores delimitadores sem precisar movê-los. Ou seja, se alguém começa com
if (pred)
{
printf("yes");
}
é fácil aparecer e adicionar outra declaração dentro do aparelho:
if (pred)
{
printf("yes");
++yes_votes;
}
A forma original tinha sido
if (pred)
{ printf("yes"); }
então teríamos que "mover" duas chaves, mas meu exemplo está mais preocupado com a segunda. Aqui, os chavetas estão delimitando o que pretende ser uma sequência de instruções , principalmente invocadas para efeito colateral.
Por outro lado, o Lisp não possui declarações; toda forma é expressão , produzindo algum valor - mesmo que em alguns casos raros (pensando no Common Lisp), esse valor seja deliberadamente escolhido como "sem valor" por meio de um (values)
formulário vazio . É menos comum encontrar seqüências de expressões , em vez de expressões aninhadas . O desejo de "abrir uma sequência de etapas até o delimitador de fechamento" não surge com tanta frequência, porque, quando as instruções desaparecem e os valores de retorno se tornam mais comuns, é mais raro ignorar o valor de retorno de uma expressão e, portanto, mais É raro avaliar uma sequência de expressões apenas para efeito colateral.
No Common Lisp, o progn
formulário é uma exceção (assim como seus irmãos):
(progn
(exp-ignored-return-1)
(exp-ignored-return-2)
(exp-taken-return))
Aqui, progn
avalia as três expressões em ordem, mas descarta os valores de retorno das duas primeiras. Você pode imaginar escrever esse último parêntese de fechamento em sua própria linha, mas observe novamente que, como a última forma é especial aqui ( embora não seja no sentido comum de Lisp de ser especial ), com tratamento distinto, é mais provável que alguém adicione novos expressões no meio da sequência, em vez de apenas "adicionar outra até o fim", pois os chamadores seriam afetados não apenas por quaisquer novos efeitos colaterais, mas por uma provável alteração no valor de retorno.
Fazendo uma simplificação grosseira, os parênteses na maioria das partes de um programa Lisp estão delimitando argumentos passados para funções - assim como em linguagens C - e não delimitando blocos de instrução. Pelas mesmas razões, tendemos a manter os parênteses delimitando uma chamada de função em C perto dos argumentos, assim como fazemos no Lisp, com menos motivação para desviar desse agrupamento próximo.
O fechamento dos parênteses é muito menos importante do que o recuo do formulário onde eles são abertos. Com o tempo, aprende-se a ignorar os parênteses e a escrever e ler pela forma - como fazem os programadores de Python. No entanto, não deixe que essa analogia o leve a pensar que a remoção completa dos parênteses valeria a pena. Não, esse é um debate mais bem guardado comp.lang.lisp
.