Azúcar sintáctica
En informática, el azúcar sintáctico es la sintaxis dentro de un lenguaje de programación diseñado para facilitar la lectura o la expresión de las cosas. Hace que el lenguaje sea "más dulce" para uso humano: las cosas se pueden expresar de manera más clara, más concisa o en un estilo alternativo que algunos prefieran. El azúcar sintáctico suele ser una forma abreviada de una operación común que también podría expresarse en una forma alternativa más detallada: el programador tiene la opción de usar la forma más corta o la forma más larga, pero generalmente usará la forma más corta ya que es más corto y más fácil de escribir y leer.
Por ejemplo, muchos lenguajes de programación proporcionan una sintaxis especial para hacer referencia y actualizar elementos de matriz. De manera abstracta, una referencia de matriz es un procedimiento de dos argumentos: una matriz y un vector de subíndice, que podría expresarse como get_array(Array, vector(i,j))
. En su lugar, muchos idiomas proporcionan una sintaxis como Array[i,j]
. De manera similar, la actualización de un elemento de matriz es un procedimiento que consta de tres argumentos, por ejemplo set_array(Array, vector(i,j), value)
, pero muchos lenguajes también proporcionan sintaxis como Array[i,j] = valor.
Una construcción en un idioma es azúcar sintáctica si se puede eliminar del idioma sin ningún efecto sobre lo que el idioma puede hacer: la funcionalidad y el poder expresivo seguirán siendo los mismos.
Los procesadores de lenguaje, incluidos los compiladores y los analizadores estáticos, a menudo expanden las construcciones azucaradas a sus equivalentes más detallados antes del procesamiento, un proceso que a veces se denomina "desugaring".
Orígenes
El término azúcar sintáctico fue acuñado por Peter J. Landin en 1964 para describir la sintaxis superficial de un lenguaje de programación simple similar a ALGOL que se definió semánticamente en términos de las expresiones aplicativas del cálculo lambda, centrado en reemplazar léxicamente λ con "donde".
Los lenguajes de programación posteriores, como CLU, ML y Scheme, ampliaron el término para referirse a la sintaxis dentro de un lenguaje que podría definirse en términos de un núcleo de lenguaje de construcciones esenciales; las características convenientes de nivel superior podrían ser "desazucaradas" y se descompone en ese subconjunto. Esta es, de hecho, la práctica matemática usual de construir a partir de primitivas.
Basándose en la distinción de Landin entre las construcciones esenciales del lenguaje y el azúcar sintáctico, en 1991, Matthias Felleisen propuso una codificación del "poder expresivo" para alinearse con "creencias generalizadas" en la literatura. Definió "más expresivo" para significar que sin las construcciones del lenguaje en cuestión, un programa tendría que ser completamente reorganizado.
Ejemplos notables
- En COBOL, muchas de las palabras clave intermedias son azúcar sintáctica que se puede omitir opcionalmente. Por ejemplo, la frase
MOVE A B.
y la sentenciaMOVE A TO B.
realizar exactamente la misma función, pero la segunda hace que la acción sea más clara. - Operadores de asignación aumentada o de asignación compuesta: Por ejemplo,
a += b
equivale aa = a + b
en C y idiomas similares, suponiendoa
no tiene efectos secundarios como sia
es una variable regular. Algunos idiomas, como Python pueden permitir la sobrecarga de operadores de asignación aumentada, por lo que pueden comportarse de manera diferente a los estándar. - En Perl,
unless (condition) {...}
es azúcar sintáctica paraif (not condition) {...}
. Además, cualquier declaración puede ser seguida por una condición, por lo questatement if condition
equivale aif (condition) {statement}
, pero el primero es más naturalmente formateado en una sola línea. - En el idioma C, el
a[i]
notación es azúcar sintáctica para*(a + i)
. Del mismo modo,a->x
notación es azúcar sintáctica para acceder a los miembros usando el operador de dereferencias(*a).x
. - El
using
declaración en C# asegura que ciertos objetos estén dispuestos correctamente. El compilador amplía la declaración en un bloque de prueba final. - El lenguaje C# permite que las variables sean declaradas
var x = expr
, que permite al compilador inferir el tipo dex
de la expresiónexpr
, en lugar de requerir una declaración explícita de tipo. Del mismo modo, C++ permiteauto x = expr
desde C++11 y Java permitevar x = expr
desde Java 11. - Comprensiones de la lista de pitones (como
[x*x for x in range(10)]
para una lista de plazas) y decoradores (como@staticmethod
). - En Haskell, una cadena, denotada en comillas, es semánticamente equivalente a una lista de caracteres.
- En la colección tidyverse de paquetes R, la tubería, denotado por
%>%
, declara que los datos (o la salida de la función) anteriores a la tubería servirán como el primer argumento para la función después de la tubería. Entonces,x %>% f(y)
equivale af(x,y)
. - En SQL, un mero
JOIN
es equivalente a unINNER JOIN
, este último aclarando que la declaración de unión es específicamente una operación de unión interna en lugar de una operación de unión externa. Del mismo modo, puede omitir elOUTER
de laLEFT OUTER JOIN
,RIGHT OUTER JOIN
yFULL OUTER JOIN
. - Métodos de llamada in OOP languages in the form of
myObject.myMethod(parameter1, parameter2, parameter3)
es azúcar sintáctica para llamar una función global comomyMethod(myObject, parameter1, parameter2, parameter3)
. La referencia al objeto se transmite como un argumento oculto, generalmente accesible desde dentro del método comothis
. - Un parámetro llamado por referencia es azúcar sintáctica para pasar técnicamente un puntero como el parámetro, pero sintácticamente manejando como la variable misma, para evitar la constante referencia puntero en el código dentro de la función.
- En Java, un
import
declaración permite al compilador encontrar clases que no se especifican de otra manera con nombres completamente calificados. Por ejemploimport javax.swing.*;
permite al programador hacer referencia a un objeto Swing comojavax.swing.JButton
usando el nombre más cortoJButton
.
Crítica
Algunos programadores sienten que estas funciones de usabilidad de sintaxis no son importantes o son completamente frívolas. En particular, las formas sintácticas especiales hacen que un lenguaje sea menos uniforme y su especificación más compleja, y pueden causar problemas a medida que los programas se vuelven grandes y complejos. Esta vista está particularmente extendida en la comunidad Lisp, ya que Lisp tiene una sintaxis muy simple y regular, y la sintaxis superficial se puede modificar fácilmente. Por ejemplo, Alan Perlis bromeó una vez en 'Epigrams on Programming', en una referencia a los lenguajes delimitados por corchetes, que 'el azúcar sintáctico causa cáncer en los puntos y comas'.
Términos derivados
Sal sintáctica
La metáfora se ha ampliado acuñando el término sal sintáctica, que indica una función diseñada para dificultar la escritura de código incorrecto. Específicamente, la sal sintáctica es un aro que los programadores deben atravesar solo para demostrar que saben lo que está sucediendo, en lugar de expresar una acción del programa. Por ejemplo, en Java y Pascal, asignar un valor flotante a una variable declarada como int sin una sintaxis adicional que indique explícitamente esa intención dará como resultado un error de compilación, mientras que C y C++ truncarán automáticamente cualquier flotante asignado a un int. Sin embargo, esto no es sintaxis, sino semántica.
En C#, al ocultar un miembro de clase heredado, se emite una advertencia del compilador a menos que se use la palabra clave new
para especificar que la ocultación es intencional. Para evitar posibles errores debido a la similitud de la sintaxis de la instrucción switch con la de C o C++, C# requiere un break
para cada etiqueta case
no vacía de un switch
(a menos que se use goto
, return
o throw
), aunque no permite fall-through implícito . (Usar goto
y especificar la etiqueta subsiguiente produce un fall-through similar a C/C++).
La sal sintáctica puede frustrar su propósito al hacer que el código sea ilegible y, por lo tanto, empeorar su calidad; en casos extremos, la parte esencial del código puede ser más corta que la sobrecarga introducida para satisfacer los requisitos del idioma.
Una alternativa a la sal sintáctica es generar advertencias del compilador cuando existe una alta probabilidad de que el código sea el resultado de un error, una práctica común en los compiladores modernos de C/C++.
Sacarina sintáctica
Otras extensiones son sacarina sintáctica y jarabe sintáctico, es decir, sintaxis gratuita que no facilita la programación.
Tipos azucarados
Se dice que los tipos de datos con soporte sintáctico central son "tipos azucarados". Los ejemplos comunes incluyen cadenas delimitadas por comillas, llaves para objetos y tipos de registros, y corchetes para matrices.
Contenido relacionado
Shigeru Miyamoto
UTF-8
Kilobyte