Azúcar sintáctica

La versión actual de la página aún no ha sido revisada por colaboradores experimentados y puede diferir significativamente de la versión revisada el 14 de febrero de 2015; las comprobaciones requieren 40 ediciones .

El azúcar sintáctico en un lenguaje de programación es una característica  sintáctica  que no afecta el comportamiento del programa pero hace que el lenguaje sea más fácil de usar.

Puede ser cualquier elemento de sintaxis que le dé al programador una forma alternativa de escribir una construcción sintáctica ya en el lenguaje que sea más conveniente, más conciso o similar a otra forma común de escribir, o que ayude a escribir programas con buen estilo.

Definición

El azúcar sintáctico es cualquier elemento sintáctico, mecanismo, método de descripción disponible en un lenguaje de programación que duplica otro elemento o mecanismo disponible en el lenguaje, pero es más conveniente de usar, es más conciso, parece más natural o es más familiar ( similar a elementos similares en otros idiomas), o simplemente se percibe mejor al leer un programa por una persona. El punto clave es que el azúcar sintáctico, en teoría, siempre se puede eliminar de un idioma sin perder sus capacidades: todo lo que se puede escribir con azúcar sintáctico se puede escribir en el mismo idioma sin él. Por lo tanto, el azúcar sintáctico solo pretende facilitar al programador la escritura del programa.

El concepto de azúcar sintáctico es en gran medida arbitrario. Su uso supone que de todo el conjunto de construcciones sintácticas disponibles en el lenguaje, uno puede destacar algún "conjunto básico" que proporciona la funcionalidad del lenguaje, y medios sintácticos adicionales, que, si se desea, pueden expresarse utilizando el conjunto básico. ; el último será azúcar sintáctico para un idioma dado. Sin embargo, muchos diseños son intercambiables y no siempre es posible decir con certeza cuáles son básicos y cuáles adicionales. Por ejemplo, hay cuatro tipos de bucles en Modula-2 : un bucle de condición previa , un bucle de condición posterior , un bucle de paso y un bucle incondicional . Teóricamente, los primeros tres tipos de ciclos pueden expresarse fácilmente en términos del último. ¿Son, entonces, azúcar sintáctico? Por lo general, no lo dicen, aunque formalmente se incluyen en la definición anterior.

La asignación de algunas construcciones al azúcar sintáctico es ambigua por razones históricas. Por ejemplo, el lenguaje C y sus descendientes tienen los operadores de asignación de incremento , decremento y compuesto ( ++, --, +=y -=otros). La introducción de estos operadores en el lenguaje se debió a la necesidad de admitir la optimización manual de los programas, ya que el código que los usaba podía traducirse en instrucciones de máquina más eficientes (“ ++a” se tradujo a una instrucción INC, y una expresión similar “ a=a+1” a todo un grupo de instrucciones). El desarrollo de la tecnología de optimización de código ha hecho que dicha optimización manual no tenga sentido; ahora los compiladores generan el mismo código para las versiones "larga" y "corta" de la operación. Como resultado, los operadores abreviados se han convertido en azúcar sintáctico, aunque originalmente no lo eran.

¿"Azúcar sintáctico" o "Basura léxica"?

En algunos casos, el concepto de "azúcar sintáctico" se interpreta de manera más amplia que "una forma diferente de escribir para construcciones sintácticas ya existentes". Jack Crenshaw en ¡Construyamos un compilador! [1] aplica este término a elementos sintácticos que no son necesarios para la correcta compilación del programa, pero que se incluyen en el lenguaje únicamente para comodidad del programador y para la legibilidad del programa:

Después de todo, la gente también debería estar leyendo programas... Las fichas de azúcar sirven como puntos de referencia útiles para ayudarlo a mantenerse en el camino...

Un ejemplo de tal azúcar sintáctico es "entonces" en la declaración "si" o "hacer" en la declaración "mientras", así como un punto y coma: el compilador determina sin ambigüedades el final de la condición y el lugar donde termina la declaración sin ellos, pero la presencia de estas construcciones hace que el programa sea más legible. Obviamente, la interpretación estrecha del concepto de "azúcar sintáctico" es incompatible con la amplia: en C o en Pascal es imposible escribir operadores de otra forma, sin "entonces", "hacer" y punto y coma. En tal caso, es apropiado hablar de " basura de sintaxis ". Teniendo en cuenta que las palabras adicionales en un lenguaje de programación son tokens adicionales, sería más correcto usar el término " basura léxica " [2] . Por otro lado, no es del todo correcto llamar a tales elementos "extra" del lenguaje "basura", porque en realidad pueden afectar significativamente la calidad de la programación, ya que la presencia de redundancia en la sintaxis facilita al compilador. para localizar errores en el código. Considere un ejemplo en algún lenguaje condicional similar a BASIC, donde la palabra entonces es opcional en la declaración condicional y un punto y coma entre las declaraciones, y el signo igual puede denotar, según la posición, tanto la igualdad lógica como la asignación:

si a > b y k = 20 f = 10

Aquí "a>b y k=20" es la condición, y "f=10" es la rama "eso". Sin embargo, si el programador omite o elimina accidentalmente el operador "y", la construcción se convierte en:

si a > b k = 20 f = 10

El programa permanecerá sintácticamente correcto, pero la condición será simplemente "a>b", y la rama "eso", dependiendo de las reglas del lenguaje, será "k=20", que ha pasado de ser una condición a una asignación, o ambos operadores "k=20 f= diez". Como resultado del error, se violará la condición y se destruirá el valor de la variable k. Dado que el programa permanecerá sintácticamente correcto cuando se introduzca un error lógico, el compilador no notará el error. Requerir la presencia obligatoria de la palabra de servicio "entonces" entre la condición y el operador hará que el compilador detecte un error de sintaxis en la condición. El punto y coma obligatorio entre los operadores también permitirá que el compilador detecte un error: la ausencia de un punto y coma después del operador "k=20". Por lo tanto, la presencia de tokens de "azúcar", como cualquier redundancia en el lenguaje en general, conduce al hecho de que los errores lógicos en el código se convierten en errores sintácticos y pueden ser detectados por el compilador.

Origen

El  término azúcar sintáctico fue acuñado por Peter J. Landin en 1964 para describir la sintaxis superficial de un lenguaje similar a Algol simple , definido semánticamente en términos de expresiones aplicativas de cálculo lambda , seguido de un reemplazo puramente léxico de λ con where.

Ejemplos

Matrices en C

Las matrices en C son bloques en la memoria . Se accede a los elementos de la matriz a través de un puntero al comienzo del bloque de memoria (es decir, al comienzo de la matriz) y el desplazamiento del elemento en relación con la dirección de inicio. Esto se puede escribir sin usar la sintaxis especial para matrices ( a - puntero al comienzo de la matriz, i - índice de elementos): *(a + i), pero el lenguaje proporciona una sintaxis especial: a[i]. Curiosamente, también se puede usar la forma i[a], que es bastante lógica debido a la conmutatividad de la operación de suma.

Redefiniendo Operadores

La redefinición de operadores , respaldada por muchos lenguajes de programación, también se puede atribuir al azúcar sintáctico . En principio, cualquier operación puede enmarcarse como un procedimiento (función, método). La redefinición de operadores le permite realizar operaciones creadas por el programador externamente de la misma manera que las integradas en el lenguaje [3] [4] .

Propiedades

Otro ejemplo de azúcar sintáctico es el concepto de "propiedades" respaldado por muchos lenguajes de programación modernos. Se refiere a la declaración en clase de pseudo-campos que externamente se comportan como campos de clase (tienen nombre, tipo, permiten asignación y lectura), pero en realidad no lo son. Cada acceso de propiedad es traducido por el compilador en una llamada de método de acceso. Las propiedades son completamente innecesarias (los accesores también se pueden llamar directamente) y se usan simplemente por conveniencia, ya que el código que usa propiedades parece algo más simple y claro.

Crítica

No todos los programadores consideran la presencia de azúcar sintáctico en los lenguajes de programación y su uso por parte de los programadores como una bendición. Es conocido el punto de vista de Niklaus Wirth , que es compartido por una parte de la comunidad programadora: según él, cualquier extensión del lenguaje que no sea provocada por la necesidad lo empeora, pues conlleva a la complicación del traductor y, en consecuencia, a una disminución de su fiabilidad y rendimiento. Al mismo tiempo, la complejidad de aprender el idioma y la complejidad de mantener los programas están aumentando. Además, el mismo hecho de que haya herramientas sintácticas adicionales a menudo juega un papel provocador: anima al programador a recurrir a varios trucos sintácticos en lugar de analizar el problema más profundamente e implementar algoritmos más eficientes. Estas opiniones se reflejan en los lenguajes de la familia Oberón , que son muy simples y prácticamente desprovistos de azúcar sintáctico.

Es conocido el aforismo de Alan Perlis : "El azúcar sintáctico causa cáncer de punto y coma" . El punto y coma ( ;), si bien es una parte obligatoria de la mayoría de los lenguajes de programación populares, incluso si es inútil en un lenguaje nuevo, se deja como un elemento opcional ya que la mayoría de los programadores tienen un fuerte hábito de usarlo. En el original, el aforismo juega con la consonancia de las palabras inglesas punto y coma ("punto y coma") y colon , el último de los cuales significa no solo un colon, sino también el intestino grueso ( cáncer de colon  - "cáncer de colon").

Más a menudo, las críticas se dirigen a tipos individuales de azúcar sintáctico que se encuentran con frecuencia: operaciones de redefinición, propiedades, operaciones complejas (como la operación condicional ternaria ). Los argumentos de los críticos, básicamente, se reducen al hecho de que tales herramientas, de hecho, no hacen que el programa sea más simple, más claro, más eficiente o más corto, sino que conducen a un desperdicio adicional de recursos y complican la percepción, y de ahí el mantenimiento del programa.

Sal de sintaxis

En contraste con "azúcar sintáctico", el concepto de " sal sintáctica " ( sal sintáctica en inglés  ) [5] en la jerga de los programadores se refiere a construcciones técnicamente inútiles en un lenguaje de programación que las reglas del lenguaje requieren usar cuando se realiza una ejecución potencialmente insegura. comportamiento. Se introducen en el lenguaje sólo para que, al usarlos, el programador confirme que la acción dudosa fue realizada por él conscientemente, y no es un error accidental o el resultado de un malentendido. Al igual que el "azúcar sintáctico", la "sal sintáctica" no amplía las capacidades del lenguaje y el compilador no la necesita para compilar correctamente el programa; está destinado exclusivamente a personas que utilizan ese idioma. Un ejemplo clásico de una "sal sintáctica" bien conocida y ampliamente utilizada son los comandos de conversión de tipo de datos incorporados que se encuentran en casi cualquier lenguaje de tipado estático. Formalmente, estos comandos son superfluos (como demuestra el C clásico, en el que se permite cualquier tipo de conversión y se realiza de forma automática), pero en lenguajes donde su uso es obligatorio, el programador se ve obligado a prestar atención cada vez que realiza una potencialmente mezcla de tipos peligrosa, que a menudo indica un error lógico en el programa. Dependiendo del rigor del lenguaje de programación, el uso de una "sal de sintaxis" puede ser obligatorio u opcional. En el primer caso, el compilador percibe su ausencia como un error de sintaxis, en el segundo caso, emite una advertencia durante la traducción, que el programador puede ignorar.

A diferencia del "azúcar sintáctico", que expande la libertad de expresión del programador, la "sal sintáctica" la reduce, requiriendo "sin razón" escribir construcciones largas. The Jargon File dice que "la sal de sintaxis es mala porque aumenta la presión arterial de un hacker". De hecho, al escribir pequeños programas creados y mantenidos por una sola persona, las precauciones pueden parecer redundantes, sin embargo, en el desarrollo industrial de grandes sistemas de software apoyados por grandes equipos de programadores, a menudo, además, no de la más alta calificación, la "sal sintáctica" ayuda para no cometer errores en el desarrollo y comprender mejor el código escrito por otros desarrolladores.

Ejemplos:

  • La directiva overrideen Delphi indica explícitamente que el método marcado por ella reemplaza el método virtual de la clase padre. La presencia de esta directiva requiere que el compilador verifique que la firma de los métodos anulados y anulados coincida, de modo que si se realiza un cambio en la clase base, el programador se verá obligado a realizar los mismos cambios en las clases descendientes; de lo contrario, el el programa no se compila.
Cabe señalar que en C++ , el método virtual se reemplazó inicialmente cuando las firmas coincidían, pero en el estándar C++11 se agregó una directiva overrideque funciona de la misma manera que en Delphi. Su uso es opcional, pero recomendado por razones de seguridad.
  • Una operación reinterpret_casten C++ proporciona una conversión de tipos no segura. La operación no produce ningún código, solo permite que el programador omita la verificación de tipos. El único punto de su uso es una indicación directa de que la conversión de tipo no segura se usó intencionalmente.
  • Palabra clave unsafeen Rust en firmas de funciones y antes de bloques de código.

Notas

  1. Jack Crenshaw, "¡Construyamos un compilador!", Sección Syntactic Sugar (enlace descendente) . Consultado el 21 de abril de 2013. Archivado desde el original el 10 de junio de 2015. 
  2. Azúcar sintáctico . Consultado el 25 de enero de 2015. Archivado desde el original el 22 de mayo de 2015.
  3. Landín, 1964 .
  4. Abelson, Sussman, Sussman, 1996 , Capítulo 1, nota al pie 11.
  5. sal sintáctica . Consultado el 24 de mayo de 2011. Archivado desde el original el 12 de junio de 2003.

Literatura

Enlaces