Por que a comunidade Lisp prefere acumular todos os parênteses no final da função:
(defn defer-expensive [cheap expensive]
(if-let [good-enough (force cheap)]
good-enough
(force expensive)))
Por que não empregar uma convenção como C ou Java?
Bem, ok, o Lisp é muito mais antigo que esses idiomas, mas estou falando dos Lispers contemporâneos.
(defn defer-expensive [cheap expensive]
(if-let [good-enough (force cheap)]
good-enough
(force expensive)
)
)
Nota: o snippet de código é do livro "The Joy of Clojure".
lisp
clojure
coding-standards
Quíron
fonte
fonte
Respostas:
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
é fácil aparecer e adicionar outra declaração dentro do aparelho:
A forma original tinha sido
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):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
.fonte
(let ((var1 expr1) more-bindings-to-be-added) ...)
, ou(list element1 more-elements-to-be-added)
Porque isso não ajuda. Usamos recuo para mostrar a estrutura do código. Se queremos separar blocos de código, usamos linhas realmente vazias.
Como a sintaxe do Lisp é tão consistente, os parênteses são o guia definitivo para o recuo, tanto para o programador quanto para o editor.
(Para mim, a questão é: por que os programadores C e Java gostam de usar o aparelho?)
Apenas para demonstrar, assumindo que esses operadores estavam disponíveis em uma linguagem semelhante a C:
Duas chaves de fechamento fecham dois níveis de aninhamento. A sintaxe está obviamente correta. Em analogia à sintaxe do Python, os chavetas são apenas tokens INDENT e DEDENT explícitos.
Obviamente, esse pode não ser o TM "estilo único" , mas acredito que seja apenas um acidente e um hábito histórico.
fonte
)
para]
ou vice-versa), então você sabe que você fechou a quantidade certa, mesmo se você não verificar os níveis de recuo.O código é muito mais compacto então. O movimento no editor é por expressões s de qualquer maneira, para que você não precise desse espaço para edição. O código é lido principalmente pela estrutura e frases - não seguindo delimitadores.
fonte
vim
para fazer isso?vimacs.vim
plugin . : PLispers, você sabe, com ódio bletcherous que seja, não é um certo je ne sais quoi para o segundo exemplo:
No começo, eu não conseguia identificar a fonte do fascínio, por assim dizer, e então percebi que faltava apenas um gatilho:
Voilà!
Vou praticar agora o meu domínio sobre gangster Lisp!
fonte
No meu caso, considero as linhas dedicadas aos delimitadores um desperdício de espaço na tela e, quando você escreve código em C, há também o estilo de
Por que as pessoas colocam a chave de abertura na mesma linha do "se" para economizar espaço e porque parece redundante ter sua própria linha quando o "se" já tem sua própria linha.
Você alcança o mesmo resultado reunindo os parênteses no final. Em C pareceria estranho porque as instruções terminam em ponto-e-vírgula e o par de colchetes não abre assim
é como aquela chave de fechamento no final, parece fora de lugar. abre assim
fornecendo uma visão clara do bloco e seus limites com '{' & '}'
E com a ajuda de um editor que corresponde aos parênteses destacando-os como o vim, você pode ir até o final, onde todos os parênteses estão agrupados e movê-los facilmente, combinar todas as parênteses de abertura e ver o formulário lisp aninhado
você pode colocar o cursor no ponto de fechamento no meio e destacar o ponto de abertura do if-let.
fonte