Uno dei motivi per cui le lingue basate su Algol incoraggiano le parentesi graffe sulla propria linea è quello di incoraggiare l'aggiunta di più linee tra le parentesi delimitanti senza dover spostare le parentesi graffe. Cioè, se uno inizia con
if (pred)
{
printf("yes");
}
è facile venire e aggiungere un'altra dichiarazione tra parentesi graffe:
if (pred)
{
printf("yes");
++yes_votes;
}
Era stata la forma originale
if (pred)
{ printf("yes"); }
allora dovremmo aver "spostato" due parentesi graffe, ma il mio esempio è più interessato a quest'ultimo. Qui, le parentesi graffe stanno delimitando ciò che si intende essere una sequenza di affermazioni , per lo più invocate per effetti collaterali.
Al contrario, a Lisp mancano le dichiarazioni; ogni forma è espressione , che produce un valore - anche se in alcuni rari casi (pensando al Common Lisp), quel valore viene deliberatamente scelto come "nessun valore" tramite una (values)
forma vuota . È meno comune trovare sequenze di espressioni , al contrario delle espressioni nidificate . Il desiderio di "aprire una sequenza di passaggi fino al delimitatore di chiusura" non sorge così spesso, poiché man mano che le istruzioni scompaiono e i valori di ritorno diventano valuta più comune, è più raro ignorare il valore di ritorno di un'espressione, e quindi di più raro valutare una sequenza di espressioni per il solo effetto collaterale.
In Common Lisp, il progn
modulo è un'eccezione (così come i suoi fratelli):
(progn
(exp-ignored-return-1)
(exp-ignored-return-2)
(exp-taken-return))
Qui, progn
valuta le tre espressioni in ordine, ma scarta i valori di ritorno delle prime due. Potresti immaginare di scrivere l'ultima parentesi di chiusura sulla sua stessa linea, ma nota ancora che poiché l'ultima forma è speciale qui (non nel senso comune di Lisp di essere speciale , però), con un trattamento distinto, è più probabile che si aggiungano nuovi espressioni nel mezzo della sequenza, piuttosto che semplicemente "aggiungerne un'altra alla fine", poiché i chiamanti verrebbero quindi influenzati non solo da eventuali nuovi effetti collaterali, ma piuttosto da una probabile modifica del valore di ritorno.
Facendo una semplificazione grossolana, le parentesi nella maggior parte delle parti di un programma Lisp stanno delimitando gli argomenti passati alle funzioni, proprio come nei linguaggi simili a C, e non delimitando i blocchi di istruzioni. Per gli stessi motivi tendiamo a mantenere le parentesi che delimitano una chiamata di funzione in C attorno agli argomenti, così facciamo anche lo stesso in Lisp, con meno motivazione a deviare da quel raggruppamento stretto.
La chiusura delle parentesi ha un'importanza molto inferiore rispetto al rientro del modulo in cui si aprono. Col tempo, si impara a ignorare le parentesi e a scrivere e leggere per forma, proprio come fanno i programmatori Python. Tuttavia, non lasciare che questa analogia ti induca a pensare che rimuovere completamente le parentesi sarebbe utile. No, è un dibattito per cui è meglio salvare comp.lang.lisp
.