stringtranslate.com

Lenguaje de programación

El código fuente de un programa informático en C. Las líneas grises son comentarios que explican el programa a los humanos. Cuando se compila y se ejecuta , arrojará como resultado " ¡Hola, mundo! ".

Un lenguaje de programación es un sistema de notación para escribir programas de computadora . [1]

Los lenguajes de programación se describen en términos de su sintaxis (forma) y semántica (significado), generalmente definidas por un lenguaje formal . Los lenguajes suelen proporcionar características como un sistema de tipos , variables y mecanismos para el manejo de errores . Se requiere una implementación de un lenguaje de programación para ejecutar programas, es decir, un intérprete o un compilador . Un intérprete ejecuta directamente el código fuente, mientras que un compilador produce un programa ejecutable .

La arquitectura informática ha influido mucho en el diseño de los lenguajes de programación, y los más comunes ( lenguajes imperativos , que implementan operaciones en un orden específico) se han desarrollado para funcionar bien en la popular arquitectura de von Neumann . Si bien los primeros lenguajes de programación estaban estrechamente vinculados al hardware , con el tiempo han desarrollado una mayor abstracción para ocultar los detalles de implementación y lograr una mayor simplicidad.

Se han desarrollado miles de lenguajes de programación, a menudo clasificados como imperativos, funcionales , lógicos u orientados a objetos , para una amplia variedad de usos. Muchos aspectos del diseño de lenguajes de programación implican concesiones; por ejemplo, el manejo de excepciones simplifica el manejo de errores, pero a costa del rendimiento. La teoría de lenguajes de programación es el subcampo de la informática que estudia el diseño, la implementación, el análisis, la caracterización y la clasificación de lenguajes de programación.

Definiciones

Los lenguajes de programación se diferencian de los lenguajes naturales en que los lenguajes naturales se utilizan para la interacción entre personas, mientras que los lenguajes de programación están diseñados para permitir que los humanos comuniquen instrucciones a las máquinas. [ cita requerida ]

El término lenguaje informático a veces se utiliza indistintamente con el de "lenguaje de programación". [2] Sin embargo, el uso de estos términos varía entre los distintos autores.

En un uso, los lenguajes de programación se describen como un subconjunto de los lenguajes informáticos. [3] De manera similar, el término "lenguaje informático" puede usarse en contraste con el término "lenguaje de programación" para describir los lenguajes utilizados en informática pero que no se consideran lenguajes de programación [ cita requerida ] , por ejemplo, los lenguajes de marcado . [4] [5] [6] Algunos autores restringen el término "lenguaje de programación" a los lenguajes Turing completos . [1] [7] La ​​mayoría de los lenguajes de programación prácticos son Turing completos, [8] y como tales son equivalentes en los programas que pueden calcular.

Otro uso considera a los lenguajes de programación como construcciones teóricas para programar máquinas abstractas y a los lenguajes informáticos como el subconjunto de los mismos que se ejecutan en computadoras físicas, que tienen recursos de hardware finitos. [9] John C. Reynolds enfatiza que los lenguajes de especificación formal son lenguajes de programación tanto como los lenguajes destinados a la ejecución. También sostiene que los formatos de entrada textuales e incluso gráficos que afectan el comportamiento de una computadora son lenguajes de programación, a pesar del hecho de que comúnmente no son Turing-completos, y señala que la ignorancia de los conceptos de los lenguajes de programación es la razón de muchos fallos en los formatos de entrada. [10]

Historia

Primeros desarrollos

Los primeros ordenadores programables se inventaron a finales de la década de 1940, y con ellos, los primeros lenguajes de programación. [11] Los primeros ordenadores se programaban en lenguajes de programación de primera generación (1GL), lenguaje de máquina (instrucciones sencillas que podían ser ejecutadas directamente por el procesador). Este código era muy difícil de depurar y no era portable entre diferentes sistemas informáticos. [12] Con el fin de mejorar la facilidad de programación, se inventaron los lenguajes ensambladores (o lenguajes de programación de segunda generación —2GL), que se apartaban del lenguaje de máquina para hacer que los programas fueran más fáciles de entender para los humanos, aunque no aumentaron la portabilidad. [13]

Inicialmente, los recursos de hardware eran escasos y costosos, mientras que los recursos humanos eran más baratos. Por lo tanto, se favorecieron los lenguajes engorrosos que consumían mucho tiempo de uso, pero que estaban más cerca del hardware para una mayor eficiencia. [14] La introducción de lenguajes de programación de alto nivel ( lenguajes de programación de tercera generación, 3GL) revolucionó la programación. Estos lenguajes abstrajeron los detalles del hardware y, en su lugar, fueron diseñados para expresar algoritmos que los humanos pudieran entender más fácilmente. Por ejemplo, las expresiones aritméticas ahora se podían escribir en notación simbólica y luego traducir a código de máquina que el hardware pudiera ejecutar. [13] En 1957, se inventó Fortran (FORmula TRANslation). A menudo considerado el primer lenguaje de programación de alto nivel compilado , [13] [15] Fortran se ha seguido utilizando hasta el siglo XXI. [16]

Década de 1960 y 1970

Dos personas utilizando un mainframe IBM 704 (el primer hardware que admitía aritmética de punto flotante ) en 1957. Fortran fue diseñado para esta máquina. [17] [16]

Alrededor de 1960, se desarrollaron los primeros mainframes (computadoras de propósito general), aunque solo podían ser operadas por profesionales y el costo era extremo. Los datos e instrucciones se ingresaban mediante tarjetas perforadas , lo que significa que no se podía agregar ninguna entrada mientras el programa estaba en ejecución. Por lo tanto, los lenguajes desarrollados en esta época están diseñados para una interacción mínima. [18] Después de la invención del microprocesador , las computadoras en la década de 1970 se volvieron drásticamente más baratas. [19] Las nuevas computadoras también permitieron una mayor interacción del usuario, que fue apoyada por lenguajes de programación más nuevos. [20]

Lisp , implementado en 1958, fue el primer lenguaje de programación funcional . [21] A diferencia de Fortran, admite recursión y expresiones condicionales , [22] y también introdujo la gestión dinámica de memoria en un montón y la recolección automática de basura . [23] Durante las siguientes décadas, Lisp dominó las aplicaciones de inteligencia artificial . [24] En 1978, otro lenguaje funcional, ML , introdujo tipos inferidos y parámetros polimórficos . [20] [25]

Después de que ALGOL (lenguaje ALGOrithmic) se lanzara en 1958 y 1960, [26] se convirtió en el estándar en la literatura informática para describir algoritmos . Aunque su éxito comercial fue limitado, la mayoría de los lenguajes imperativos populares, incluidos C , Pascal , Ada , C++ , Java y C# , descienden directa o indirectamente de ALGOL 60. [27] [16] Entre sus innovaciones adoptadas por lenguajes de programación posteriores se incluyen una mayor portabilidad y el primer uso de la gramática BNF libre de contexto . [28] Simula , el primer lenguaje que admitió la programación orientada a objetos (incluidos subtipos , despacho dinámico y herencia ), también desciende de ALGOL y logró un éxito comercial. [29] C, otro descendiente de ALGOL, ha mantenido su popularidad hasta el siglo XXI. C permite el acceso a operaciones de máquina de nivel inferior más que otros lenguajes contemporáneos. Su potencia y eficiencia, generadas en parte con operaciones de puntero flexibles , tienen el costo de dificultar la escritura de código correcto. [20]

Prolog , diseñado en 1972, fue el primer lenguaje de programación lógica que se comunicaba con una computadora mediante notación lógica formal. [30] [31] Con la programación lógica, el programador especifica un resultado deseado y permite que el intérprete decida cómo lograrlo. [32] [31]

De los años 1980 a los años 2000

Una pequeña selección de libros de texto sobre lenguajes de programación

Durante la década de 1980, la invención de la computadora personal transformó los roles para los cuales se usaban los lenguajes de programación. [33] Los nuevos lenguajes introducidos en la década de 1980 incluyeron C++, un superconjunto de C que puede compilar programas en C pero también admite clases y herencia . [34] Ada y otros lenguajes nuevos introdujeron soporte para concurrencia . [35] El gobierno japonés invirtió fuertemente en los llamados lenguajes de quinta generación que agregaron soporte para concurrencia a las construcciones de programación lógica, pero estos lenguajes fueron superados por otros lenguajes que admitían concurrencia. [36] [37]

Debido al rápido crecimiento de Internet y la World Wide Web en la década de 1990, se introdujeron nuevos lenguajes de programación para dar soporte a las páginas web y a las redes . [38] Java , basado en C++ y diseñado para una mayor portabilidad entre sistemas y seguridad, disfrutó de un éxito a gran escala porque estas características son esenciales para muchas aplicaciones de Internet. [ 39] [40] Otro desarrollo fue el de los lenguajes de scripting de tipado dinámico —Python , JavaScript , PHP y Ruby— diseñados para producir rápidamente pequeños programas que coordinan aplicaciones existentes . Debido a su integración con HTML , también se han utilizado para crear páginas web alojadas en servidores . [41] [42]

De los años 2000 al presente

Durante la década de 2000, hubo una desaceleración en el desarrollo de nuevos lenguajes de programación que alcanzaron una popularidad generalizada. [43] Una innovación fue la programación orientada a servicios , diseñada para explotar sistemas distribuidos cuyos componentes están conectados por una red. Los servicios son similares a los objetos en la programación orientada a objetos, pero se ejecutan en un proceso separado. [44] C# y F# polinizaron ideas cruzadas entre la programación imperativa y funcional. [45] Después de 2010, varios lenguajes nuevos ( Rust , Go , Swift , Zig y Carbon) compitieron por el software crítico para el rendimiento para el que históricamente se había utilizado C. [46] La mayoría de los nuevos lenguajes de programación utilizan tipado estático , mientras que unos pocos lenguajes nuevos utilizan tipado dinámico como Ring y Julia . [47] [48]

Algunos de los nuevos lenguajes de programación se clasifican como lenguajes de programación visual como Scratch , LabVIEW y PWCT . Además, algunos de estos lenguajes mezclan el uso de la programación textual y visual como Ballerina . [49] [50] [51] [52] Además, esta tendencia llevó al desarrollo de proyectos que ayudan en el desarrollo de nuevos VPL como Blockly de Google . [53] Muchos motores de juegos como Unreal y Unity también agregaron soporte para scripting visual. [54] [55]

Elementos

Todo lenguaje de programación incluye elementos fundamentales para describir datos y las operaciones o transformaciones que se aplican a ellos, como por ejemplo sumar dos números o seleccionar un elemento de una colección. Estos elementos se rigen por reglas sintácticas y semánticas que definen su estructura y significado, respectivamente.

Sintaxis

Árbol de análisis de código Python con tokenización insertada
El resaltado de sintaxis se utiliza a menudo para ayudar a los programadores a reconocer elementos del código fuente. El lenguaje mencionado anteriormente es Python .

La forma superficial de un lenguaje de programación se conoce como sintaxis . La mayoría de los lenguajes de programación son puramente textuales; utilizan secuencias de texto que incluyen palabras, números y puntuación, de forma muy similar a los lenguajes naturales escritos. Por otro lado, algunos lenguajes de programación son gráficos y utilizan relaciones visuales entre símbolos para especificar un programa.

La sintaxis de un lenguaje describe las posibles combinaciones de símbolos que forman un programa sintácticamente correcto. El significado que se le da a una combinación de símbolos se maneja mediante la semántica (ya sea formal o codificada en una implementación de referencia ). Dado que la mayoría de los lenguajes son textuales, este artículo analiza la sintaxis textual.

La sintaxis de un lenguaje de programación suele definirse mediante una combinación de expresiones regulares (para la estructura léxica ) y la forma Backus-Naur (para la estructura gramatical ). A continuación se muestra una gramática sencilla basada en Lisp :

expresión ::= átomo | listaátomo ::= número | símbolonúmero ::= [+-]?['0'-'9']+símbolo ::= ['A'-'Z''a'-'z'].*lista ::= '(' expresión* ')'

Esta gramática especifica lo siguiente:

Los siguientes son ejemplos de secuencias de tokens bien formadas en esta gramática: 12345, ()y (a b c232 (1)).

No todos los programas sintácticamente correctos son semánticamente correctos. Muchos programas sintácticamente correctos están mal formados, según las reglas del lenguaje, y pueden (dependiendo de la especificación del lenguaje y de la solidez de la implementación) generar un error en la traducción o ejecución. En algunos casos, dichos programas pueden exhibir un comportamiento indefinido . Incluso cuando un programa está bien definido dentro de un lenguaje, puede tener un significado que no es el que pretendía la persona que lo escribió.

Usando el lenguaje natural como ejemplo, puede que no sea posible asignar un significado a una oración gramaticalmente correcta o la oración puede ser falsa:

El siguiente fragmento del lenguaje C es sintácticamente correcto, pero realiza operaciones que no están definidas semánticamente (la operación *p >> 4no tiene significado para un valor que tiene un tipo complejo y p->imno está definida porque el valor de pes el puntero nulo ):

complejo * p = NULL ; complejo abs_p = sqrt ( * p >> 4 + p -> im );          

Si se omitiera la declaración de tipo en la primera línea, el programa generaría un error en la variable indefinida pdurante la compilación. Sin embargo, el programa seguiría siendo sintácticamente correcto, ya que las declaraciones de tipo solo brindan información semántica.

La gramática necesaria para especificar un lenguaje de programación se puede clasificar por su posición en la jerarquía de Chomsky . La sintaxis de la mayoría de los lenguajes de programación se puede especificar utilizando una gramática de tipo 2, es decir, son gramáticas libres de contexto . [56] Algunos lenguajes, incluidos Perl y Lisp, contienen construcciones que permiten la ejecución durante la fase de análisis. Los lenguajes que tienen construcciones que permiten al programador alterar el comportamiento del analizador hacen del análisis de sintaxis un problema indecidible , y generalmente difuminan la distinción entre análisis y ejecución. [57] A diferencia del sistema de macros de Lisp y los bloques de Perl BEGIN, que pueden contener cálculos generales, las macros de C son simplemente reemplazos de cadenas y no requieren la ejecución de código. [58]

Semántica

El término semántica se refiere al significado de los lenguajes, en oposición a su forma (sintaxis).

Semántica estática

La semántica estática define restricciones en la estructura de textos válidos que son difíciles o imposibles de expresar en formalismos sintácticos estándar. [1] [ verificación fallida ] Para lenguajes compilados, la semántica estática incluye esencialmente aquellas reglas semánticas que pueden comprobarse en tiempo de compilación. Los ejemplos incluyen comprobar que cada identificador se declara antes de su uso (en lenguajes que requieren tales declaraciones) o que las etiquetas en los brazos de una declaración de caso son distintas. [59] Muchas restricciones importantes de este tipo, como comprobar que los identificadores se utilizan en el contexto apropiado (por ejemplo, no agregar un entero a un nombre de función), o que las llamadas a subrutinas tienen el número y tipo apropiado de argumentos, se pueden hacer cumplir definiéndolas como reglas en una lógica llamada sistema de tipos . Otras formas de análisis estáticos como el análisis de flujo de datos también pueden ser parte de la semántica estática. Los lenguajes de programación como Java y C# tienen análisis de asignación definida , una forma de análisis de flujo de datos, como parte de su respectiva semántica estática.

Semántica dinámica

Una vez que se han especificado los datos, se debe dar instrucciones a la máquina para que realice operaciones con ellos. Por ejemplo, la semántica puede definir la estrategia mediante la cual se evalúan las expresiones como valores, o la manera en que las estructuras de control ejecutan condicionalmente las sentencias . La semántica dinámica (también conocida como semántica de ejecución ) de un lenguaje define cómo y cuándo las diversas construcciones de un lenguaje deben producir un comportamiento del programa. Hay muchas maneras de definir la semántica de ejecución. El lenguaje natural se utiliza a menudo para especificar la semántica de ejecución de los lenguajes que se utilizan habitualmente en la práctica. Una cantidad significativa de investigación académica se dedica a la semántica formal de los lenguajes de programación , que permite especificar la semántica de ejecución de manera formal. Los resultados de este campo de investigación han tenido una aplicación limitada en el diseño e implementación de lenguajes de programación fuera del ámbito académico.

Sistema de tipos

Un tipo de datos es un conjunto de valores permitidos y operaciones que se pueden realizar sobre estos valores. [60] El sistema de tipos de cada lenguaje de programación define qué tipos de datos existen, el tipo de una expresión y cómo funcionan la equivalencia de tipos y la compatibilidad de tipos en el lenguaje. [61]

Según la teoría de tipos , un lenguaje está completamente tipado si la especificación de cada operación define los tipos de datos a los que se aplica la operación. [62] Por el contrario, un lenguaje no tipado, como la mayoría de los lenguajes ensambladores , permite realizar cualquier operación sobre cualquier dato, generalmente secuencias de bits de varias longitudes. [62] En la práctica, aunque pocos lenguajes están completamente tipados, la mayoría ofrecen un grado de tipado. [62]

Debido a que los diferentes tipos (como los enteros y los flotantes ) representan valores de manera diferente, se producirán resultados inesperados si se utiliza un tipo cuando se espera otro. La comprobación de tipos marcará este error, normalmente en tiempo de compilación (la comprobación de tipos en tiempo de ejecución es más costosa). [63] Con la tipificación fuerte , los errores de tipo siempre se pueden detectar a menos que las variables se conviertan explícitamente a un tipo diferente. La tipificación débil se produce cuando los lenguajes permiten la conversión implícita, por ejemplo, para permitir operaciones entre variables de diferentes tipos sin que el programador haga una conversión de tipo explícita. Cuantos más casos en los que se permita esta conversión de tipo , menos errores de tipo se pueden detectar. [64]

Tipos comúnmente admitidos

Los primeros lenguajes de programación a menudo solo admitían tipos numéricos integrados, como el entero (con signo y sin signo) y el de punto flotante (para admitir operaciones con números reales que no son enteros). La mayoría de los lenguajes de programación admiten varios tamaños de flotantes (a menudo llamados float y double ) y enteros según el tamaño y la precisión requeridos por el programador. Almacenar un entero en un tipo que es demasiado pequeño para representarlo conduce a un desbordamiento de entero . La forma más común de representar números negativos con tipos con signo es el complemento a dos , aunque también se utiliza el complemento a uno . [65] Otros tipos comunes incluyen Boolean —que es verdadero o falso— y character —tradicionalmente un byte , suficiente para representar todos los caracteres ASCII . [66]

Las matrices son un tipo de datos cuyos elementos, en muchos lenguajes, deben constar de un único tipo de longitud fija. Otros lenguajes definen las matrices como referencias a datos almacenados en otro lugar y admiten elementos de distintos tipos. [67] Dependiendo del lenguaje de programación, las secuencias de múltiples caracteres, llamadas cadenas , pueden admitirse como matrices de caracteres o como su propio tipo primitivo . [68] Las cadenas pueden tener una longitud fija o variable, lo que permite una mayor flexibilidad a costa de un mayor espacio de almacenamiento y más complejidad. [69] Otros tipos de datos que pueden admitirse incluyen listas , [70] matrices asociativas (no ordenadas) a las que se accede mediante claves, [71] registros en los que los datos se asignan a nombres en una estructura ordenada, [72] y tuplas , similares a los registros pero sin nombres para los campos de datos. [73] Los punteros almacenan direcciones de memoria, que normalmente hacen referencia a ubicaciones en el montón donde se almacenan otros datos. [74]

El tipo definido por el usuario más simple es un tipo ordinal cuyos valores se pueden asignar al conjunto de números enteros positivos. [75] Desde mediados de la década de 1980, la mayoría de los lenguajes de programación también admiten tipos de datos abstractos , en los que la representación de los datos y las operaciones están ocultas al usuario , que solo puede acceder a una interfaz . [76] Los beneficios de la abstracción de datos pueden incluir mayor confiabilidad, menor complejidad, menor potencial de colisión de nombres y permitir que se cambie la estructura de datos subyacente sin que el cliente necesite alterar su código. [77]

Tipificación estática y dinámica

En la tipificación estática , todas las expresiones tienen sus tipos determinados antes de que se ejecute un programa, normalmente en tiempo de compilación. [62] La mayoría de los lenguajes de programación de tipado estático más utilizados requieren que los tipos de las variables se especifiquen explícitamente. En algunos lenguajes, los tipos son implícitos; una forma de esto es cuando el compilador puede inferir tipos basándose en el contexto. La desventaja de la tipificación implícita es la posibilidad de que los errores pasen desapercibidos. [78] La inferencia de tipos completa se ha asociado tradicionalmente con lenguajes funcionales como Haskell y ML . [79]

Con el tipado dinámico, el tipo no se asocia a la variable sino solo al valor codificado en ella. Una única variable puede reutilizarse para un valor de un tipo diferente. Aunque esto proporciona más flexibilidad al programador, se hace a costa de una menor fiabilidad y una menor capacidad del lenguaje de programación para comprobar si hay errores. [80] Algunos lenguajes permiten variables de un tipo de unión a las que se puede asignar cualquier tipo de valor, en una excepción a sus reglas habituales de tipado estático. [81]

Concurrencia

En informática, se pueden ejecutar múltiples instrucciones simultáneamente. Muchos lenguajes de programación admiten la concurrencia a nivel de instrucción y a nivel de subprograma. [82] En el siglo XXI, la potencia de procesamiento adicional en las computadoras provenía cada vez más del uso de procesadores adicionales, lo que requiere que los programadores diseñen software que haga uso de múltiples procesadores simultáneamente para lograr un rendimiento mejorado. [83] Los lenguajes interpretados como Python y Ruby no admiten el uso simultáneo de múltiples procesadores. [84] Otros lenguajes de programación sí admiten la gestión de datos compartidos entre diferentes subprocesos controlando el orden de ejecución de instrucciones clave mediante el uso de semáforos , controlando el acceso a datos compartidos mediante monitor o habilitando el paso de mensajes entre subprocesos. [85]

Manejo de excepciones

Muchos lenguajes de programación incluyen controladores de excepciones, una sección de código activada por errores de tiempo de ejecución que puede lidiar con ellos de dos maneras principales: [86]

Algunos lenguajes de programación permiten dedicar un bloque de código para que se ejecute independientemente de si ocurre una excepción antes de que se alcance el código; esto se denomina finalización. [87]

Existe una compensación entre una mayor capacidad para manejar excepciones y un rendimiento reducido. [88] Por ejemplo, aunque los errores de índice de matriz son comunes [89] C no los verifica por razones de rendimiento. [88] Aunque los programadores pueden escribir código para capturar excepciones definidas por el usuario, esto puede saturar un programa. Las bibliotecas estándar en algunos lenguajes, como C, usan sus valores de retorno para indicar una excepción. [90] Algunos lenguajes y sus compiladores tienen la opción de activar y desactivar la capacidad de manejo de errores, ya sea temporal o permanentemente. [91]

Diseño e implementación

Una de las influencias más importantes en el diseño de lenguajes de programación ha sido la arquitectura de computadoras . Los lenguajes imperativos , el tipo más comúnmente usado, fueron diseñados para funcionar bien en la arquitectura de von Neumann , la arquitectura de computadoras más común. [92] En la arquitectura de von Neumann, la memoria almacena tanto datos como instrucciones, mientras que la CPU que ejecuta instrucciones sobre los datos está separada, y los datos deben ser canalizados de ida y vuelta a la CPU. Los elementos centrales en estos lenguajes son las variables, la asignación y la iteración , que es más eficiente que la recursión en estas máquinas. [93]

Muchos lenguajes de programación han sido diseñados desde cero, modificados para satisfacer nuevas necesidades y combinados con otros lenguajes. Muchos han caído en desuso con el tiempo. [ cita requerida ] El nacimiento de los lenguajes de programación en la década de 1950 fue estimulado por el deseo de hacer un lenguaje de programación universal adecuado para todas las máquinas y usos, evitando la necesidad de escribir código para diferentes computadoras. [94] A principios de la década de 1960, la idea de un lenguaje universal fue rechazada debido a los diferentes requisitos de la variedad de propósitos para los que se escribía el código. [95]

Compensaciones

Las cualidades deseables de los lenguajes de programación incluyen legibilidad, capacidad de escritura y confiabilidad. [96] Estas características pueden reducir el costo de capacitación de los programadores en un lenguaje, la cantidad de tiempo necesario para escribir y mantener programas en el lenguaje, el costo de compilar el código y aumentar el rendimiento en tiempo de ejecución. [97]

El diseño de lenguajes de programación a menudo implica concesiones. [107] Por ejemplo, las características para mejorar la confiabilidad generalmente se consiguen a costa del rendimiento. [108] Una mayor expresividad debido a una gran cantidad de operadores hace que escribir código sea más fácil, pero se consigue a costa de la legibilidad. [108]

Se ha propuesto la programación en lenguaje natural como una forma de eliminar la necesidad de un lenguaje especializado para la programación. Sin embargo, este objetivo sigue siendo lejano y sus beneficios están abiertos al debate. Edsger W. Dijkstra sostuvo que el uso de un lenguaje formal es esencial para evitar la introducción de construcciones sin sentido. [109] Alan Perlis también desestimó la idea. [110]

Especificación

La especificación de un lenguaje de programación es un artefacto que los usuarios del lenguaje y los implementadores pueden usar para acordar si un fragmento de código fuente es un programa válido en ese lenguaje y, de ser así, cuál será su comportamiento.

Una especificación de lenguaje de programación puede adoptar varias formas, incluidas las siguientes:

Implementación

Una implementación de un lenguaje de programación es la conversión de un programa en código de máquina que puede ser ejecutado por el hardware. El código de máquina puede entonces ser ejecutado con la ayuda del sistema operativo . [114] La forma más común de interpretación en el código de producción es mediante un compilador , que traduce el código fuente a través de un lenguaje de nivel intermedio en código de máquina, conocido como ejecutable . Una vez que el programa se compila, se ejecutará más rápidamente que con otros métodos de implementación. [115] Algunos compiladores pueden proporcionar una mayor optimización para reducir el uso de memoria o computación cuando se ejecuta el ejecutable, pero aumentando el tiempo de compilación. [116]

Otro método de implementación es ejecutar el programa con un intérprete , que traduce cada línea de software a código de máquina justo antes de que se ejecute. Aunque puede facilitar la depuración, la desventaja de la interpretación es que se ejecuta de 10 a 100 veces más lento que un ejecutable compilado. [117] Los métodos de interpretación híbridos proporcionan algunos de los beneficios de la compilación y algunos de los beneficios de la interpretación a través de la compilación parcial. Una forma que esto toma es la compilación justo a tiempo , en la que el software se compila con anticipación en un lenguaje intermedio y luego en código de máquina inmediatamente antes de la ejecución. [118]

Lenguajes propietarios

Aunque la mayoría de los lenguajes de programación más utilizados tienen especificaciones e implementaciones totalmente abiertas, muchos de ellos existen solo como lenguajes de programación propietarios, cuya implementación está disponible solo a través de un único proveedor, que puede afirmar que dicho lenguaje propietario es su propiedad intelectual. Los lenguajes de programación propietarios suelen ser lenguajes específicos de un dominio o lenguajes de programación internos para un único producto; algunos lenguajes propietarios se utilizan solo internamente dentro de un proveedor, mientras que otros están disponibles para usuarios externos. [ cita requerida ]

Algunos lenguajes de programación existen en el límite entre lo propietario y lo abierto; por ejemplo, Oracle Corporation afirma tener derechos de propiedad sobre algunos aspectos del lenguaje de programación Java , [119] y el lenguaje de programación C# de Microsoft , que tiene implementaciones abiertas de la mayoría de las partes del sistema, también tiene Common Language Runtime (CLR) como un entorno cerrado. [120]

Muchos lenguajes propietarios son ampliamente utilizados, a pesar de su naturaleza propietaria; algunos ejemplos incluyen MATLAB , VBScript y Wolfram Language . Algunos lenguajes pueden hacer la transición de cerrados a abiertos; por ejemplo, Erlang fue originalmente el lenguaje de programación interno de Ericsson. [121]

Los lenguajes de programación de código abierto son particularmente útiles para aplicaciones de ciencia abierta , mejorando la capacidad de replicación y compartición de código. [122]

Usar

Se han creado miles de lenguajes de programación diferentes, principalmente en el campo de la informática. [123] Los proyectos de software individuales suelen utilizar cinco lenguajes de programación o más. [124]

Los lenguajes de programación se diferencian de la mayoría de las demás formas de expresión humana en que requieren un mayor grado de precisión y completitud. Al utilizar un lenguaje natural para comunicarse con otras personas, los autores y hablantes humanos pueden ser ambiguos y cometer pequeños errores, y aun así esperar que se entienda su intención. Sin embargo, en sentido figurado, las computadoras "hacen exactamente lo que se les dice que hagan" y no pueden "entender" qué código pretendía escribir el programador. La combinación de la definición del lenguaje, un programa y las entradas del programa deben especificar por completo el comportamiento externo que ocurre cuando se ejecuta el programa, dentro del dominio de control de ese programa. Por otro lado, las ideas sobre un algoritmo se pueden comunicar a los humanos sin la precisión requerida para la ejecución mediante el uso de pseudocódigo , que intercala el lenguaje natural con el código escrito en un lenguaje de programación.

Un lenguaje de programación proporciona un mecanismo estructurado para definir fragmentos de datos y las operaciones o transformaciones que se pueden llevar a cabo automáticamente sobre esos datos. Un programador utiliza las abstracciones presentes en el lenguaje para representar los conceptos involucrados en un cálculo. Estos conceptos se representan como una colección de los elementos más simples disponibles (llamados primitivos ). [125] La programación es el proceso mediante el cual los programadores combinan estos primitivos para componer nuevos programas o adaptar los existentes a nuevos usos o a un entorno cambiante.

Los programas de una computadora pueden ejecutarse en un proceso por lotes sin interacción humana, o un usuario puede escribir comandos en una sesión interactiva de un intérprete . En este caso, los "comandos" son simplemente programas, cuya ejecución está encadenada. Cuando un lenguaje puede ejecutar sus comandos a través de un intérprete (como un shell de Unix u otra interfaz de línea de comandos ), sin compilar, se denomina lenguaje de scripting . [126]

Medición del uso del lenguaje

Determinar cuál es el lenguaje de programación más utilizado es difícil, ya que la definición de uso varía según el contexto. Un lenguaje puede ocupar la mayor cantidad de horas de programación, otro tiene más líneas de código y un tercero puede consumir la mayor cantidad de tiempo de CPU. Algunos lenguajes son muy populares para tipos particulares de aplicaciones. Por ejemplo, COBOL todavía es fuerte en el centro de datos corporativo, a menudo en grandes mainframes ; [127] [128] Fortran en aplicaciones científicas y de ingeniería; Ada en aplicaciones aeroespaciales, de transporte, militares, en tiempo real e integradas; y C en aplicaciones integradas y sistemas operativos. Otros lenguajes se utilizan regularmente para escribir muchos tipos diferentes de aplicaciones.

Se han propuesto varios métodos para medir la popularidad de una lengua, cada uno de ellos sujeto a un sesgo diferente sobre lo que se mide:

Al combinar y promediar información de varios sitios de Internet, stackify.com informó los diez lenguajes de programación más populares (en orden descendente por popularidad general): Java , C , C++ , Python , C# , JavaScript , VB .NET , R , PHP y MATLAB . [132]

A partir de junio de 2024, los cinco principales lenguajes de programación según la medición del índice TIOBE son Python , C++ , C , Java y C# . TIOBE proporciona una lista de los 100 principales lenguajes de programación según su popularidad y actualiza esta lista todos los meses. [133]

Dialectos, sabores e implementaciones

Un dialecto de un lenguaje de programación o de un lenguaje de intercambio de datos es una variación o extensión (relativamente pequeña) del lenguaje que no cambia su naturaleza intrínseca. Con lenguajes como Scheme y Forth , los estándares pueden ser considerados insuficientes, inadecuados o ilegítimos por los implementadores, por lo que a menudo se desviarán del estándar, creando un nuevo dialecto . En otros casos, se crea un dialecto para su uso en un lenguaje específico del dominio , a menudo un subconjunto. En el mundo Lisp , la mayoría de los lenguajes que utilizan sintaxis básica de expresión S y semántica similar a Lisp se consideran dialectos Lisp, aunque varían enormemente como lo hacen, por ejemplo, Racket y Clojure . Como es común que un lenguaje tenga varios dialectos, puede resultar bastante difícil para un programador inexperto encontrar la documentación adecuada. El lenguaje BASIC tiene muchos dialectos .

Clasificaciones

Los lenguajes de programación a menudo se clasifican en cuatro categorías principales: imperativo , funcional , lógico y orientado a objetos . [134]

Aunque los lenguajes de marcado no son lenguajes de programación, algunos tienen extensiones que admiten una programación limitada. Además, hay lenguajes de propósito especial que no se pueden comparar fácilmente con otros lenguajes de programación. [138]

Véase también

Referencias

  1. ^ abc Aaby, Anthony (2004). Introducción a los lenguajes de programación. Archivado desde el original el 8 de noviembre de 2012 . Consultado el 29 de septiembre de 2012 .
  2. ^ Robert A. Edmunds, Glosario estándar de terminología informática de Prentice-Hall, Prentice-Hall, 1985, pág. 91
  3. ^ Pascal Lando, Anne Lapujade, Gilles Kassel y Frédéric Fürst, Towards a General Ontology of Computer Programs Archivado el 7 de julio de 2015 en Wayback Machine , ICSOFT 2007 Archivado el 27 de abril de 2010 en Wayback Machine , pp. 163–170
  4. ^ XML en 10 puntos Archivado el 6 de septiembre de 2009 en Wayback Machine. W3C , 1999, "XML no es un lenguaje de programación".
  5. ^ Powell, Thomas (2003). HTML y XHTML: la referencia completa . McGraw-Hill. pág. 25. ISBN 978-0-07-222942-4HTML no es un lenguaje de programación.
  6. ^ Dykes, Lucinda; Tittel, Ed (2005). XML para tontos (4.ª ed.). Wiley. pág. 20. ISBN 978-0-7645-8845-7... es un lenguaje de marcado, no un lenguaje de programación.
  7. ^ En términos matemáticos, esto significa que el lenguaje de programación es Turing-completo MacLennan, Bruce J. (1987). Principles of Programming Languages ​​. Oxford University Press. p. 1. ISBN 978-0-19-511306-8.
  8. ^ "Completitud de Turing". www.cs.odu.edu . Archivado desde el original el 16 de agosto de 2022 . Consultado el 5 de octubre de 2022 .
  9. ^ R. Narasimhan, Lenguajes de programación y computadoras: una metateoría unificada, pp. 189—247 en Franz Alt, Morris Rubinoff (eds.) Avances en computadoras, Volumen 8, Academic Press, 1994, ISBN 0-12-012108-5 , p.215: "[...] el modelo [...] para lenguajes de computación difiere de aquel [...] para lenguajes de programación en sólo dos aspectos. En un lenguaje de computación, sólo hay un número finito de nombres —o registros— que pueden asumir sólo un número finito de valores —o estados— y estos estados no se distinguen más en términos de ningún otro atributo. [nota del autor:] Esto puede sonar como una verdad de Perogrullo, pero sus implicaciones son de largo alcance. Por ejemplo, implicaría que cualquier modelo para lenguajes de programación, al fijar algunos de sus parámetros o características, debería ser reducible de manera natural a un modelo para lenguajes de computación". 
  10. ^ John C. Reynolds, "Algunas reflexiones sobre la enseñanza de la programación y los lenguajes de programación", SIGPLAN Notices , Volumen 43, Número 11, noviembre de 2008, pág. 109
  11. ^ Gabbrielli y Martini 2023, pag. 519.
  12. ^ Gabbrielli y Martini 2023, págs. 520–521.
  13. ^ abc Gabbrielli y Martini 2023, pag. 521.
  14. ^ Gabbrielli y Martini 2023, pag. 522.
  15. ^ Sebesta 2012, pág. 42.
  16. ^ abc Gabbrielli y Martini 2023, pag. 524.
  17. ^ Sebesta 2012, págs. 42–44.
  18. ^ Gabbrielli y Martini 2023, págs. 523–524.
  19. ^ Gabbrielli y Martini 2023, pag. 527.
  20. ^ abc Gabbrielli y Martini 2023, pag. 528.
  21. ^ "Cómo Lisp se convirtió en el lenguaje de programación de Dios". twobithistory.org . Archivado desde el original el 10 de abril de 2024 . Consultado el 10 de abril de 2024 .
  22. ^ Sebesta 2012, págs. 47–48.
  23. ^ Gabbrielli y Martini 2023, pag. 526.
  24. ^ Sebesta 2012, pág. 50.
  25. ^ Sebesta 2012, págs. 701–703.
  26. ^ Gabbrielli y Martini 2023, págs. 524–525.
  27. ^ Sebesta 2012, págs. 56–57.
  28. ^ Gabbrielli y Martini 2023, pag. 525.
  29. ^ Gabbrielli y Martini 2023, págs. 526–527.
  30. ^ Gabbrielli y Martini 2023, pag. 531.
  31. ^ desde Sebesta 2012, pág. 79.
  32. ^ Gabbrielli y Martini 2023, pag. 530.
  33. ^ Gabbrielli y Martini 2023, págs. 532–533.
  34. ^ Gabbrielli y Martini 2023, pag. 534.
  35. ^ Gabbrielli y Martini 2023, págs. 534–535.
  36. ^ Gabbrielli y Martini 2023, pag. 535.
  37. ^ Sebesta 2012, pág. 736.
  38. ^ Gabbrielli y Martini 2023, pag. 536.
  39. ^ Gabbrielli y Martini 2023, págs. 536–537.
  40. ^ Sebesta 2012, págs. 91–92.
  41. ^ Gabbrielli y Martini 2023, págs. 538–539.
  42. ^ Sebesta 2012, págs. 97–99.
  43. ^ Gabbrielli y Martini 2023, pag. 542.
  44. ^ Gabbrielli y Martini 2023, págs. 474–475, 477, 542.
  45. ^ Gabbrielli y Martini 2023, págs. 542–543.
  46. ^ Gabbrielli y Martini 2023, pag. 544.
  47. ^ Bezanson, J., Karpinski, S., Shah, VB y Edelman, A., 2012. Julia: Un lenguaje dinámico rápido para computación técnica. Preimpresión de arXiv arXiv:1209.5145.
  48. ^ Ayouni, M. y Ayouni, M., 2020. Tipos de datos en Ring. Programación Ring inicial: de principiante a profesional, págs. 51-98.
  49. ^ Sáez-López, JM, Román-González, M. y Vázquez-Cano, E., 2016. Lenguajes de programación visual integrados en el currículo de la escuela primaria: un estudio de caso de dos años utilizando “Scratch” en cinco escuelas. Computers & Education, 97, pp.129-141.
  50. ^ Fayed, MS, Al-Qurishi, M., Alamri, A. y Al-Daraiseh, AA, 2017, marzo. PWCT: lenguaje visual para aplicaciones y sistemas de IoT y computación en la nube. En Actas de la Segunda Conferencia Internacional sobre Internet de las cosas, datos y computación en la nube (pp. 1-5).
  51. ^ Kodosky, J., 2020. LabVIEW. Actas de la ACM sobre lenguajes de programación, 4(HOPL), págs. 1-54.
  52. ^ Fernando, A. y Warusawithana, L., 2020. Programación de bailarinas principiantes: de principiante a profesional. Apress.
  53. ^ Baluprithviraj, KN, Bharathi, KR, Chendhuran, S. y Lokeshwaran, P., marzo de 2021. Puerta inteligente basada en inteligencia artificial con detección de mascarillas. En la Conferencia internacional sobre inteligencia artificial y sistemas inteligentes (ICAIS) de 2021 (págs. 543-548). IEEE.
  54. ^ Sewell, B., 2015. Diseño de scripts visuales para Unreal Engine. Packt Publishing Ltd.
  55. ^ Bertolini, L., 2018. Desarrollo práctico de juegos sin codificación: creación de juegos 2D y 3D con Visual Scripting en Unity. Packt Publishing Ltd.
  56. ^ Michael Sipser (1996). Introducción a la teoría de la computación . PWS Publishing. ISBN 978-0-534-94728-6.Sección 2.2: Autómatas Pushdown, págs. 101-114.
  57. ^ Jeffrey Kegler, "Perl y la indecidibilidad Archivado el 17 de agosto de 2009 en Wayback Machine ", The Perl Review . Los artículos 2 y 3 prueban, utilizando respectivamente el teorema de Rice y la reducción directa al problema de la detención , que el análisis sintáctico de programas Perl es, en general, indecidible.
  58. ^ Marty Hall, 1995, Notas de clase: Macros Archivado el 6 de agosto de 2013 en Wayback Machine , versión PostScript Archivado el 17 de agosto de 2000 en Wayback Machine
  59. ^ Michael Lee Scott, Pragmática del lenguaje de programación , Edición 2, Morgan Kaufmann, 2006, ISBN 0-12-633951-1 , pág. 18-19 
  60. ^ Sebesta 2012, pág. 244.
  61. ^ Sebesta 2012, pág. 245.
  62. ^ abcd Andrew Cooke. «Introducción a los lenguajes informáticos». Archivado desde el original el 15 de agosto de 2012. Consultado el 13 de julio de 2012 .
  63. ^ Sebesta 2012, págs. 15, 408–409.
  64. ^ Sebesta 2012, págs. 303–304.
  65. ^ Sebesta 2012, págs. 246-247.
  66. ^ Sebesta 2012, pág. 249.
  67. ^ Sebesta 2012, pág. 260.
  68. ^ Sebesta 2012, pág. 250.
  69. ^ Sebesta 2012, pág. 254.
  70. ^ Sebesta 2012, págs. 281–282.
  71. ^ Sebesta 2012, págs. 272-273.
  72. ^ Sebesta 2012, págs. 276-277.
  73. ^ Sebesta 2012, pág. 280.
  74. ^ Sebesta 2012, págs. 289-290.
  75. ^ Sebesta 2012, pág. 255.
  76. ^ Sebesta 2012, págs. 244-245.
  77. ^ Sebesta 2012, pág. 477.
  78. ^ Sebesta 2012, pág. 211.
  79. ^ Leivant, Daniel (1983). Inferencia de tipos polimórficos . Simposio ACM SIGACT-SIGPLAN sobre Principios de lenguajes de programación. Austin, Texas: ACM Press. pp. 88–98. doi : 10.1145/567067.567077 . ISBN . 978-0-89791-090-3.
  80. ^ Sebesta 2012, págs. 212-213.
  81. ^ Sebesta 2012, págs. 284–285.
  82. ^ Sebesta 2012, pág. 576.
  83. ^ Sebesta 2012, pág. 579.
  84. ^ Sebesta 2012, pág. 585.
  85. ^ Sebesta 2012, págs. 585–586.
  86. ^ Sebesta 2012, págs. 630, 634.
  87. ^ Sebesta 2012, pág. 635.
  88. ^ desde Sebesta 2012, pág. 631.
  89. ^ Sebesta 2012, pág. 261.
  90. ^ Sebesta 2012, pág. 632.
  91. ^ Sebesta 2012, págs. 631, 635–636.
  92. ^ Sebesta 2012, pág. 18.
  93. ^ Sebesta 2012, pág. 19.
  94. ^ Nofre, Priestley y Alberts 2014, pág. 55.
  95. ^ Nofre, Priestley y Alberts 2014, pág. 60.
  96. ^ Sebesta 2012, pág. 8.
  97. ^ Sebesta 2012, págs. 16-17.
  98. ^ Sebesta 2012, págs. 8–9.
  99. ^ Sebesta 2012, págs. 9–10.
  100. ^ Sebesta 2012, págs. 12-13.
  101. ^ Sebesta 2012, pág. 13.
  102. ^ Sebesta 2012, págs. 14-15.
  103. ^ Frederick P. Brooks, Jr.: El mes mítico del hombre , Addison-Wesley, 1982, págs. 93-94
  104. ^ Busbee, Kenneth Leroy; Braunschweig, Dave (15 de diciembre de 2018). «Bibliotecas estándar». Fundamentos de programación: un enfoque estructurado modular . Consultado el 27 de enero de 2024 .
  105. ^ Sebesta 2012, pág. 15.
  106. ^ Sebesta 2012, págs. 8, 16.
  107. ^ Sebesta 2012, págs. 18, 23.
  108. ^ desde Sebesta 2012, pág. 23.
  109. ^ Dijkstra, Edsger W. Sobre la estupidez de la "programación en lenguaje natural". Archivado el 20 de enero de 2008 en Wayback Machine. EWD667.
  110. ^ Perlis, Alan (septiembre de 1982). "Epigramas sobre programación". SIGPLAN Notices Vol. 17, No. 9 . págs. 7–13. Archivado desde el original el 17 de enero de 1999.
  111. ^ Milner, R. ; M. Tofte ; R. Harper ; D. MacQueen (1997). La definición de ML estándar (revisada) . MIT Press. ISBN 978-0-262-63181-5.
  112. ^ Kelsey, Richard; William Clinger; Jonathan Rees (febrero de 1998). "Sección 7.2 Semántica formal". Informe revisado nº 5 sobre el esquema de lenguaje algorítmico . Archivado desde el original el 6 de julio de 2006.
  113. ^ ANSI – Lenguaje de programación Rexx, X3-274.1996
  114. ^ Sebesta 2012, págs. 23–24.
  115. ^ Sebesta 2012, págs. 25–27.
  116. ^ Sebesta 2012, pág. 27.
  117. ^ Sebesta 2012, pág. 28.
  118. ^ Sebesta 2012, págs. 29–30.
  119. ^ Véase: Oracle America, Inc. v. Google, Inc. [ fuente generada por el usuario ]
  120. ^ "Guía de lenguajes de programación | ComputerScience.org". ComputerScience.org . Archivado desde el original el 13 de mayo de 2018. Consultado el 13 de mayo de 2018 .
  121. ^ "Conceptos básicos". ibm.com . 10 de mayo de 2011. Archivado desde el original el 14 de mayo de 2018 . Consultado el 13 de mayo de 2018 .
  122. ^ Abdelaziz, Abdullah I.; Hanson, Kent A.; Gaber, Charles E.; Lee, Todd A. (2023). "Optimización del análisis de grandes datos del mundo real con archivos parquet en R: un tutorial paso a paso". Farmacoepidemiología y seguridad de los medicamentos . 33 (3): e5728. doi : 10.1002/pds.5728 . PMID  37984998.
  123. ^ "HOPL: una lista interactiva de lenguajes de programación". Australia: Universidad Murdoch . Archivado desde el original el 20 de febrero de 2011. Consultado el 1 de junio de 2009. Este sitio contiene 8512 idiomas.
  124. ^ Mayer, Philip; Bauer, Alexander (2015). "Análisis empírico de la utilización de múltiples lenguajes de programación en proyectos de código abierto". Actas de la 19.ª Conferencia Internacional sobre Evaluación y Valoración en Ingeniería de Software . Actas de la 19.ª Conferencia Internacional sobre Evaluación y Valoración en Ingeniería de Software – EASE '15. Nueva York, NY, EE. UU.: ACM. págs. 4:1–4:10. doi : 10.1145/2745802.2745805 . ISBN. 978-1-4503-3350-4Resultados: Encontramos (a) un número medio de 5 lenguajes por proyecto con un lenguaje principal de propósito general claramente dominante y 5 tipos de DSL de uso frecuente, (b) una influencia significativa del tamaño, número de commits y el lenguaje principal en el número de lenguajes así como ninguna influencia significativa de la edad y número de contribuidores, y (c) tres ecosistemas de lenguajes agrupados alrededor de XML, Shell/Make y HTML/CSS. Conclusiones: La programación multilenguaje parece ser común en proyectos de código abierto y es un factor que debe abordarse en las herramientas y al evaluar el desarrollo y mantenimiento de tales sistemas de software.
  125. ^ Abelson, Sussman y Sussman. "Estructura e interpretación de programas informáticos". Archivado desde el original el 26 de febrero de 2009. Consultado el 3 de marzo de 2009 .{{cite web}}: CS1 maint: multiple names: authors list (link)
  126. ^ Vicki, Brown; Morin, Rich (1999). "Lenguajes de scripting". MacTech . Archivado desde el original el 2 de diciembre de 2017.
  127. ^ Georgina Swan (21 de septiembre de 2009). «COBOL cumple 50 años». Computerworld. Archivado desde el original el 19 de octubre de 2013. Consultado el 19 de octubre de 2013 .
  128. ^ Ed Airey (3 de mayo de 2012). "7 mitos de COBOL desacreditados". developer.com. Archivado desde el original el 19 de octubre de 2013. Consultado el 19 de octubre de 2013 .
  129. ^ Nicholas Enticknap. "Encuesta sobre salarios de TI de SSL/Computer Weekly: el auge financiero impulsa el crecimiento del empleo en TI". Computer Weekly . Archivado desde el original el 26 de octubre de 2011. Consultado el 14 de junio de 2013 .
  130. ^ "Conteo de lenguajes de programación por ventas de libros". Radar.oreilly.com. 2 de agosto de 2006. Archivado desde el original el 17 de mayo de 2008.
  131. ^ Bieman, JM; Murdock, V., Encontrar código en la World Wide Web: una investigación preliminar, Actas del primer taller internacional IEEE sobre análisis y manipulación de código fuente, 2001
  132. ^ "Los lenguajes de programación más populares e influyentes de 2018". stackify.com. 18 de diciembre de 2017. Archivado desde el original el 30 de agosto de 2018. Consultado el 29 de agosto de 2018 .
  133. ^ "Índice TIOBE" . Consultado el 24 de junio de 2024 .
  134. ^ Sebesta 2012, pág. 21.
  135. ^ ab Sebesta 2012, págs. 21-22.
  136. ^ Sebesta 2012, pág. 12.
  137. ^ Sebesta 2012, pág. 22.
  138. ^ Sebesta 2012, págs. 22-23.

Lectura adicional