¿Por qué la comunidad de Lisp prefiere acumular todos los paréntesis al final de la función?
(defn defer-expensive [cheap expensive]
(if-let [good-enough (force cheap)]
good-enough
(force expensive)))
¿Por qué no emplear una convención como C o Java?
Bien, Lisp es mucho más antiguo que esos idiomas, pero estoy hablando de los Lispers contemporáneos.
(defn defer-expensive [cheap expensive]
(if-let [good-enough (force cheap)]
good-enough
(force expensive)
)
)
Nota: El fragmento de código es del libro "The Joy of Clojure".
lisp
clojure
coding-standards
Quirón
fuente
fuente
Respuestas:
Una de las razones por las cuales los lenguajes basados en Algol fomentan las llaves en su propia línea es para alentar la adición de más líneas entre las llaves delimitadoras sin tener que mover las llaves. Es decir, si uno comienza con
es fácil venir y agregar otra declaración entre llaves:
Si la forma original hubiera sido
entonces tendríamos que haber "movido" dos llaves, pero mi ejemplo está más relacionado con la última. Aquí, las llaves delimitan lo que pretende ser una secuencia de declaraciones , en su mayoría invocadas para efectos secundarios.
Por el contrario, Lisp carece de declaraciones; cada forma es expresión , dando algún valor, incluso si en algunos casos raros (pensando en Common Lisp), ese valor se elige deliberadamente para que sea "sin valores" a través de una
(values)
forma vacía . Es menos común encontrar secuencias de expresiones , a diferencia de las expresiones anidadas . El deseo de "abrir una secuencia de pasos hasta el delimitador de cierre" no surge con tanta frecuencia, porque a medida que las declaraciones desaparecen y los valores devueltos se vuelven más comunes, es más raro ignorar el valor devuelto de una expresión, y por lo tanto más Es raro evaluar una secuencia de expresiones para el efecto secundario solo.En Common Lisp, el
progn
formulario es una excepción (al igual que sus hermanos):Aquí,
progn
evalúa las tres expresiones en orden, pero descarta los valores de retorno de las dos primeras. Podría imaginarse escribiendo el último paréntesis de cierre en su propia línea, pero tenga en cuenta nuevamente que, dado que la última forma es especial aquí ( aunque no en el sentido de Common Lisp de ser especial ), con un tratamiento distinto, es más probable que se agreguen nuevos expresiones en el medio de la secuencia, en lugar de simplemente "agregar otra al final", ya que las personas que llaman no se verán afectadas por ningún efecto secundario nuevo sino por un posible cambio en el valor de retorno.Haciendo una simplificación general, los paréntesis en la mayoría de las partes de un programa Lisp delimitan argumentos pasados a funciones, al igual que en lenguajes tipo C, y no delimitan bloques de instrucciones. Por las mismas razones, tendemos a mantener los paréntesis que delimitan una llamada de función en C cerca de los argumentos, así que también hacemos lo mismo en Lisp, con menos motivación para desviarse de esa agrupación cercana.
El cierre de los paréntesis es mucho menos importante que la sangría del formulario donde se abren. Con el tiempo, uno aprende a ignorar los paréntesis y a escribir y leer por forma, al igual que los programadores de Python. Sin embargo, no dejes que esa analogía te lleve a pensar que valdría la pena eliminar los paréntesis por completo. No, ese es el debate mejor guardado
comp.lang.lisp
.fuente
(let ((var1 expr1) more-bindings-to-be-added) ...)
, o(list element1 more-elements-to-be-added)
Porque no ayuda Usamos sangría para mostrar la estructura del código. Si queremos separar bloques de código, usamos líneas realmente vacías.
Como la sintaxis de Lisp es tan consistente, los paréntesis son la guía definitiva para la sangría tanto para el programador como para el editor.
(Para mí, la pregunta es más bien por qué a los programadores de C y Java les gusta tirar sus llaves).
Solo para demostrar, asumiendo que estos operadores estaban disponibles en un lenguaje tipo C:
Dos llaves de cierre cierran dos niveles de anidación. La sintaxis es obviamente correcta. En analogía con la sintaxis de Python, las llaves son solo tokens explícitos INDENT y DEDENT.
Por supuesto, este podría no ser el TM de "un verdadero estilo de aparato ortopédico" , pero creo que es solo un accidente histórico y un hábito.
fuente
)
a]
o viceversa), para que sepa que cerró la cantidad correcta, incluso si usted no comprueba los niveles de sangría.El código es mucho más compacto entonces. El movimiento en el editor es por expresiones s de todos modos, por lo que no necesita ese espacio para editar. El código se lee principalmente por estructura y oraciones, no siguiendo delimitadores.
fuente
vim
hacer eso?vimacs.vim
complemento . : PLispers, ya saben, odio bletcherous ya que puede ser, no es cierto no sé qué con el segundo ejemplo:
Al principio no pude señalar el origen del encanto, por así decirlo, y luego me di cuenta de que solo faltaba un gatillo:
Voilà!
¡Voy a practicar mi agarre de gángster Lisp ahora!
fuente
En mi caso, encuentro que las líneas dedicadas a delimitadores son una pérdida de espacio en la pantalla, y cuando escribes código en C también existe el estilo de
¿Por qué las personas colocan la llave de apertura en la misma línea del "if" para ahorrar espacio, y porque parece redundante tener su propia línea cuando el "if" ya tiene su propia línea?
Alcanza el mismo resultado al juntar el paréntesis al final. En C se vería raro porque las declaraciones terminan en punto y coma y el par de paréntesis no se abre así
Es como ese cierre de llave al final, parece fuera de lugar. se abre así
dándole una visión clara del bloque y sus límites mediante '{' & '}'
Y con la ayuda de un editor que coincide con los paréntesis al resaltarlos como lo hace vim, puede ir al final donde se empaquetan todos los paréntesis y moverse a través de ellos fácilmente y hacer coincidir todos los paréntesis de apertura y ver el formulario lisp anidado
puede colocar el cursor en el par de cierre en el medio y resaltar el par de apertura del if-let.
fuente