La regla de sangría describe la sintaxis de un lenguaje de programación que define los límites de un bloque de código mediante la indentación . [ 1 ] [ 2 ]
El término fue acuñado por Peter Landin , posiblemente como un juego de palabras con la regla del fuera de juego en el fútbol .
Un lenguaje con reglas de fuera de juego se contrapone a un lenguaje de forma libre en el que la sangría no tiene significado sintáctico y es estrictamente una cuestión de estilo .
También se describe que el lenguaje de la regla del fuera de juego tiene una sangría significativa .
Definición
Peter Landin , en su artículo de 1966 " Los próximos 700 lenguajes de programación ", definió la regla del lado opuesto de la siguiente manera: "Cualquier token que no sea un espacio en blanco a la izquierda del primer token de este tipo en la línea anterior se considera el comienzo de una nueva declaración". [ 3 ]
Ejemplo
A continuación se muestra un ejemplo de bloques de indentación en Python , un lenguaje popular con reglas de indentación. En Python, la regla se utiliza para definir los límites de las sentencias, no de las declaraciones.
def is_even ( a : int ) -> bool :"""Determina si un número es par o impar."""si a % 2 == 0 :imprimir ( "¡Incluso!" )devolver verdaderoimprimir ( "¡Extraño!" )devolver FalsoEl cuerpo de la función comienza en la línea 2, ya que tiene una sangría de un nivel (4 espacios) más que la línea anterior. El ifcuerpo de la cláusula comienza en la línea 4, ya que tiene una sangría adicional, y termina en la línea 5, puesto que la línea 6 tiene una sangría menor, es decir, sin sangría.
Los dos puntos ( :) al final de una línea de instrucción de control son sintaxis de Python, no un aspecto de la regla de ejecución fuera de línea. La regla se puede implementar sin esta sintaxis de dos puntos.
Implementación
La regla del lado opuesto se puede implementar en la fase de análisis léxico , como en Python , donde aumentar la sangría hace que el analizador léxico genere un INDENTtoken, y disminuir la sangría hace que el analizador léxico genere un DEDENTtoken. [ 4 ] Estos tokens corresponden a la llave de apertura {y la llave de cierre }en los lenguajes que usan llaves para los bloques, y significa que la gramática de la frase no depende de si se usan llaves o sangría. Esto requiere que el analizador léxico mantenga el estado, es decir, el nivel de sangría actual, y por lo tanto puede detectar cambios en la sangría cuando esto cambia, y por lo tanto la gramática léxica no es libre de contexto : INDENTy DEDENTdepende de la información contextual del nivel de sangría anterior.
Alternativas
La principal alternativa a la delimitación de bloques mediante sangría, popularizada por el uso generalizado y la influencia del lenguaje C , consiste en ignorar los espacios en blanco y marcar los bloques explícitamente con llaves (es decir, `<br>` {y }`<br>`) u otro delimitador. Si bien esto permite mayor libertad de formato (un desarrollador podría optar por no sangrar pequeños fragmentos de código como las instrucciones `break` y `continue` ), un código con sangría deficiente podría confundir al lector, como en el caso del error ` goto fail` .
Lisp y otros lenguajes basados en expresiones S no diferencian las sentencias de las expresiones, y los paréntesis son suficientes para controlar el alcance de todas las sentencias dentro del lenguaje. Al igual que en los lenguajes con llaves, el lector (es decir, la función `read`) ignora en su mayoría los espacios en blanco. Los espacios en blanco se utilizan para separar tokens. [ 5 ] La estructura explícita del código Lisp permite la indentación automática, para formar una señal visual para los lectores humanos.
Otra alternativa es que cada bloque comience y termine con palabras clave explícitas. Por ejemplo, en ALGOL 60 y su descendiente Pascal , los bloques comienzan con la palabra clavebegin y terminan con la palabra clave end. En algunos lenguajes (pero no en Pascal), esto significa que los saltos de línea son importantes (a diferencia de los lenguajes con llaves), pero la indentación no lo es. En BASIC y Fortran , los bloques comienzan con el nombre del bloque (como ) y terminan con el nombre del bloque precedido por (por ejemplo, ). En Fortran , cada bloque también puede tener su propio nombre de bloque único, lo que agrega otro nivel de explicitud al código extenso. ALGOL 68 y el shell Bourne (sh y bash ) son similares, pero el final del bloque generalmente viene dado por el nombre del bloque escrito al revés (por ejemplo, comienza una instrucción switch y se extiende hasta el correspondiente ; de manera similar, las condicionales ... ...[ ...[ ...]IFENDEND IFcaseesacifthenelifelse] fio bucles forfor ... do... oden ALGOL68 o for... do... doneen bash).
Una variante interesante de esto ocurre en Modula-2 , un lenguaje similar a Pascal que elimina la diferencia entre bloques de una y varias líneas. Esto permite omitir el abridor de bloque ( {o ) para todos los bloques excepto los de nivel de función, requiriendo solo un token de terminación de bloque ( o ). También corrige el else colgante . Lo habitual es que el token se coloque en el mismo nivel de sangría que el resto del bloque, lo que da como resultado una estructura de bloque muy legible.BEGIN}ENDend
Una ventaja del enfoque de Fortran es que mejora la legibilidad de código largo, anidado o complejo. Un grupo de sangrías o corchetes de cierre por sí solos no proporcionan pistas contextuales sobre qué bloques se están cerrando, lo que requiere retroceder y un examen más minucioso durante la depuración . Además, los lenguajes que permiten un sufijo para palabras clave similares a END mejoran aún más dichas pistas, como continueversus continue for x, y el marcador de fin de bucle que especifica la variable de índiceNEXT I versus NEXT, y bucles con nombres únicosCYCLE X1 versus . Sin embargo, los editores de código fuenteCYCLE modernos a menudo proporcionan indicadores visuales, como resaltado de sintaxis , y características como plegado de código para ayudar a mitigar estos inconvenientes.
Productividad
En el lenguaje Scala , las primeras versiones solo permitían llaves. Scala 3 añadió la opción de usar la indentación para estructurar bloques. El diseñador Martin Odersky afirmó que esta era la forma más importante en que Scala 3 mejoró su propia productividad, ya que reduce la duración de los programas en más de un 10 % y mantiene a los programadores concentrados, por lo que recomienda su uso. [ 6 ]
Lenguajes de programación destacados
Lenguajes de programación notables con la regla del lado opuesto:
- abecedario
- Agda
- Abucheo
- Cobra
- CoffeeScript
- Converger
- Curry
- Olmo
- F# (en versiones anteriores, cuando
#lightse especifica; en versiones posteriores, cuando#light "off"no se especifica) [ 7 ] - GDScript (motor Godot)
- Haskell , [ 8 ] solo para cláusulas
where,let,do, ocase ... ofcuando se omiten las llaves - Informar 7
- ISWIM , el lenguaje abstracto que introdujo la regla
- LiveScript
- Langosta [ 9 ]
- Miranda
- MoonScript [ 10 ] [ 11 ]
- Nemerle , modo opcional
- Nim
- Occam
- PROMAL
- Pitón
- Scala , modo opcional
- Esquema , al utilizar una de las diversas solicitudes de esquema para implementaciones , la más reciente de las cuales es SRFI 119.
- Girar
- Mujer
- SG
Otros formatos de archivo
Lenguaje no programático destacable, formatos de archivo de texto con sangría significativa:
- GCode , dialecto RepRapFirmware [ 12 ]
- Haml
- Hacer , la línea con sangría de tabulación significa un comando
- Pug (anteriormente Jade), véase Comparación de motores de plantillas web
- reStructuredText [ 13 ]
- Hablar con descaro a
- Aguja
- YAML
Véase también
Referencias
- ↑ Hutton, G. (6 de diciembre de 2012). «Análisis sintáctico mediante combinadores» . En Davis, Kei; Hughes, John (eds.). Programación funcional: Actas del taller de Glasgow de 1989, 21-23 de agosto de 1989, Fraserburgh, Escocia . Springer Science & Business Media. págs. 362-364 . ISBN 9781447131663. Consultado el 3 de septiembre de 2015 .
- ↑ Turner, DA (13 de agosto de 2013). «Historia de los lenguajes de programación funcional (Ponencia invitada)» . En Loidl, Hans Wolfgang; Peña, Ricardo (eds.). Tendencias en programación funcional: XIII Simposio Internacional, TFP 2012, St Andrews, Reino Unido, 12-14 de junio de 2012, Artículos seleccionados revisados . Springer. pág. 8. ISBN 9783642404474. Consultado el 3 de septiembre de 2015 .
- ↑ Landin, PJ (marzo de 1966). "Los próximos 700 lenguajes de programación" (PDF) . Communications of the ACM . 9 (3): 157–166 . doi : 10.1145/365230.365257 . S2CID 13409665. Archivado del original (PDF) el 20 de junio de 2010. Recuperado el 28 de agosto de 2015 .
- ↑ Documentación de Python , 2. Análisis léxico : 2.1.8. Sangría
- ↑ "CLHS: Sección 2.1.4.7" .
- ↑ Odersky, Martin (17 de junio de 2020). Martin Odersky: Actualización de Scala 3 (video). YouTube. El evento ocurre entre los minutos 36:35 y 45:08. Archivado del original el 21 de diciembre de 2021. Recuperado el 25 de abril de 2021 .
- ↑ Syme, Don (20 de mayo de 2009). "Notas de la versión detalladas para la actualización CTP de F# de mayo de 2009 y las versiones Beta1 de Visual Studio 2010" . Archivado del original el 21 de enero de 2019.
- ↑ El Informe Haskell – Diseño
- ↑ Lobster, un lenguaje de programación con tipado estático y gestión de memoria en tiempo de compilación para el desarrollo de juegos y gráficos.
- ↑ MoonScript, un lenguaje que se compila a Lua
- ↑ Guía de idioma de MoonScript 0.5.0
- ↑ "Comandos meta de GCode" .
- ↑ Especificación de marcado reStructuredText – Sangría
- Temas de lenguajes de programación