Lenguaje de programación

Un lenguaje de programación , en informática , es un lenguaje formal que especifica un conjunto de instrucciones que se pueden usar para producir datos de salida: se puede usar para controlar el comportamiento de una máquina formal o una implementación de la misma (típicamente, una computadora ) o en la fase de programación de este mediante la escritura del código fuente de un programa por parte de un programador : un lenguaje de programación se considera a todos los efectos como tal si es Turing-completo .

Historia

El primer lenguaje de programación de la historia es el lenguaje mecánico utilizado por Ada Lovelace para programar la máquina de Charles Babbage , al que siguió Plankalkül de Konrad Zuse , desarrollado por él en la Suiza neutral durante la Segunda Guerra Mundial y publicado en 1946 . Plankalkül nunca se usó realmente para programar. En cambio, la programación de las primeras computadoras se hizo en código corto [1] , a partir del cual evolucionó el ensamblaje , que constituye una representación simbólica del lenguaje máquina. La única forma de control de flujo es la instrucción de salto condicional, que lleva a escribir programas que son muy difíciles de seguir lógicamente debido a los constantes saltos de un punto a otro en el código.

La mayoría de los lenguajes de programación posteriores intentaron abstraerse de este nivel básico, dando la posibilidad de representar estructuras de datos y estructuras de control más generales y más cercanas a la forma (humana) de representar los términos de los problemas a los que apuntamos. para escribir programas. Entre los primeros lenguajes de alto nivel que alcanzaron cierta popularidad estuvo Fortran , creado en 1957 por John Backus , del cual derivó posteriormente BASIC ( 1964 ) : además del salto condicional, representado con la instrucción IF, esta nueva generación de lenguajes ​​introduce nuevas estructuras de control de flujo como los bucles WHILE y FOR y las instrucciones CASE y SWITCH: de esta forma se reduce considerablemente el uso de instrucciones de salto (GOTO), lo que hace que el código sea más claro y elegante, y por lo tanto más fácil de mantener.

Tras la aparición de Fortran, nacieron una serie de otros lenguajes de programación históricos, que implementaron una serie de ideas y paradigmas innovadores : los más importantes son Lisp ( 1959 ) y ALGOL ( 1960 ). Todos los lenguajes de programación existentes en la actualidad pueden considerarse descendientes de uno o varios de estos primeros lenguajes, de los que toman prestados muchos conceptos básicos; el último gran progenitor de los lenguajes modernos fue Simula ( 1967 ), que fue el primero en introducir el concepto (entonces apenas esbozado) de objeto software . En 1970 Niklaus Wirth publicó Pascal , el primer lenguaje estructurado, con fines didácticos; en 1972 la BCPL creó primero la B (rápidamente olvidada) y luego la C , que en cambio fue un gran éxito desde el principio. En el mismo año aparece también Prolog , hasta ahora el principal ejemplo de lenguaje lógico, que aunque normalmente no se usa para el desarrollo industrial de software (debido a su ineficiencia) representa una posibilidad teórica extremadamente fascinante.

Con las primeras mini y microcomputadoras y la investigación en Palo Alto, en 1983 nació Smalltalk , el primer lenguaje verdadera y completamente orientado a objetos, inspirado en Simula y Lisp: además de estar todavía en uso hoy en día en ciertos sectores , paradigma orientado a objetos en su primera encarnación madura . Ejemplos de los lenguajes orientados a objetos actuales son Eiffel ( 1986 ), C++ (que salió el mismo año que Eiffel) y más tarde Java , clase 1995 .

Descripción

Fundamentos

Todos los lenguajes de programación existentes están definidos por un léxico , una sintaxis y una semántica y tienen:

Algunos conceptos también están presentes en la mayoría de los idiomas:

Código fuente

Programar en un lenguaje de programación dado generalmente significa escribir uno o más archivos de texto ASCII simples , llamados código fuente, que expresa el algoritmo del programa traducido al lenguaje de programación. Las fuentes, los colores y, en general, el aspecto gráfico son irrelevantes para los propósitos de la programación en sí: por esta razón, los programadores no usan programas de procesamiento de texto, sino editores de texto (como emacs y brief ) que en su lugar ofrecen funciones avanzadas de procesamiento de texto . expresiones , sustituciones condicionales y búsquedas en múltiples archivos, posibilidad de llamar a herramientas externas, etc.).

Si un editor dado es capaz de trabajar en estrecha colaboración con otras herramientas de trabajo (compilador, enlazador, intérprete, etc.: ver más abajo), entonces más que un editor estamos hablando de IDE o entorno de desarrollo integrado. Cabe señalar que algunos lenguajes de programación recientes también permiten una forma mixta de programación, en la que la redacción del código fuente ASCII también se asocia con operaciones de programación visual , a través de las cuales el programador describe algunos aspectos del programa dibujando en la pantalla. usando el ratón ; una aplicación típica de la última forma de programación es el diseño interactivo de la GUI del programa (ventanas, menús, etc.). Para ser ejecutado por el procesador, el código fuente debe ser traducido a lenguaje máquina que es el lenguaje en el que opera la máquina a nivel físico, y esto es posible a través de dos técnicas posibles: la compilación y la interpretación .

El código fuente, que contiene las instrucciones que se ejecutarán y (a menudo) algunos datos conocidos y constantes, se puede ejecutar pasándolo a un intérprete que ejecutará las instrucciones contenidas en él, lo cual es una práctica normal para los lenguajes de secuencias de comandos ; o puede ser compilado, es decir, traducido a instrucciones en lenguaje de máquina por un programa compilador : el resultado es un archivo binario 'ejecutable' ( código ejecutable ) que no necesita otros programas para ejecutarse, y también es mucho más rápido que un programa interpretado. En el pasado, la compilación ha sido la norma para todos los lenguajes de programación de propósito general; actualmente existen numerosos lenguajes interpretados y de uso general, como Java o los de la plataforma .NET , que aplican un enfoque híbrido entre las dos soluciones, utilizando un compilador para producir código en un lenguaje intermedio (llamado bytecode ) que posteriormente es interpretado. La diferencia de rendimiento entre lenguajes interpretados y compilados se ha reducido con técnicas de compilación justo a tiempo , aunque los lenguajes compilados (cuando no ensambladores ) se siguen utilizando para aplicaciones que requieren el mayor rendimiento posible.

Compilación

La compilación es el proceso por el cual el programa, escrito en un lenguaje de programación de alto nivel, es traducido a un código ejecutable por medio de otro programa llamado compilador . La compilación ofrece numerosas ventajas, en primer lugar el hecho de obtener ejecutables muy rápidos en la fase de ejecución adaptando varios parámetros de esta fase al hardware disponible; pero tiene el principal inconveniente de que es necesario compilar un ejecutable diferente para cada sistema operativo o hardware ( plataforma ) sobre el que se quiera disponer de la ejecución o se carezca de la llamada portabilidad .

Interpretación

Para solucionar el problema de la portabilidad (la dependencia o no del lenguaje de la plataforma), se han creado lenguajes basados ​​en bibliotecas compiladas (componentes) ad hoc para cada plataforma, en las que se ejecuta directamente el código fuente, por lo que no hay necesidad de una compilación en cada tipo de máquina en la que se ejecuta. El defecto de estos lenguajes es la lentitud de la ejecución; sin embargo, tienen la ventaja de permitirle usar el mismo programa sin modificaciones en múltiples plataformas. En este caso, se dice que el programa es portable .

La pérdida de rendimiento que está en la base de los lenguajes interpretados es el doble trabajo que se le encomienda a la máquina que se prepara para procesar este programa. A diferencia de un programa compilado, de hecho, cada instrucción es verificada e interpretada en cada ejecución por un intérprete . Los lenguajes interpretados se utilizan en la fase de desarrollo de un programa para evitar realizar numerosas compilaciones o cuando se quiere crear software que realice operaciones no críticas que no requieran optimizaciones en cuanto a velocidad o tamaño, pero que se beneficien más de la portabilidad. Las secuencias de comandos y todos los lenguajes orientados a la Web casi siempre se interpretan. PHP , Perl , Tcl/Tk y JavaScript y muchos otros son ejemplos concretos de interacción sin plataforma.

Hay varios intentos de hacer que los compiladores sean multiplataforma creando un nivel intermedio, una especie de semi-interpretación, como en el caso mencionado de Java ; en cambio, para los lenguajes interpretados existen intentos de generar compilaciones automáticas (o semicompilaciones) específicas de la máquina en la que se ejecutan. También existen herramientas para automatizar al máximo la compilación de un mismo programa en diferentes plataformas, por ejemplo GNU autoconf / automake , que permite crear una distribución del código fuente que puede configurarse y compilarse automáticamente en diferentes plataformas, generalmente al menos todo Unix .

Vinculación

Si el programa, como sucede a menudo, utiliza bibliotecas o está compuesto por varios módulos de software , estos deben estar 'enlazados' entre sí. La herramienta que hace esto se llama linker , y se ocupa principalmente de resolver las interconexiones entre los diferentes módulos. Existen principalmente dos tipos diferentes de enlaces: dinámicos y estáticos .

Enlace estático

Todos los módulos de programa y bibliotecas utilizados están incluidos en el ejecutable, que es grande, pero contiene todo lo necesario para su ejecución. Si se hace necesario un cambio en una de las bibliotecas, para corregir un error o un problema de seguridad , todos los programas que usan bibliotecas vinculadas estáticamente deben volver a vincularse con las nuevas versiones de las bibliotecas.

Vinculación dinámica

El sistema operativo carga las bibliotecas utilizadas cuando es necesario ( enlace dinámico ; las bibliotecas externas se denominan "DLL", bibliotecas de enlace dinámico en sistemas Microsoft Windows , mientras que "SO" Objeto compartido en sistemas similares a Unix ). El ejecutable resultante es más compacto, pero depende de la presencia de las bibliotecas utilizadas en el sistema operativo para poder ejecutarse. De esta forma, las bibliotecas se pueden actualizar una sola vez a nivel de sistema operativo, sin necesidad de volver a vincular programas. También es posible usar diferentes versiones de la misma biblioteca o usar bibliotecas personalizadas con características específicas para el host en particular. En la realización de un proyecto de software complejo, puede ocurrir que algunas partes del programa se creen como librerías, para facilitar el mantenimiento o poder utilizarlas en diferentes programas que forman parte de un mismo proyecto.

La complicación adicional es que cuando instala un programa de enlace dinámico, debe verificar las bibliotecas que usa y eventualmente instalarlas también. Los sistemas de gestión de paquetes, que se encargan de instalar programas en un sistema operativo, suelen realizar un seguimiento de estas dependencias de forma automática. En general, se prefiere la vinculación dinámica, para crear programas pequeños y, en general, reducir la memoria RAM ocupada, suponiendo que las bibliotecas necesarias ya están presentes en el sistema, o a veces distribuyéndolas junto con el programa.

Comparación entre compilación e interpretación

Estos dos métodos de creación y ejecución de un programa tienen ventajas y desventajas: la mayor ventaja de la compilación es, sin duda, la eficiencia mucho mayor en términos de rendimiento, al precio de permanecer atado a una plataforma (combinación de arquitectura de hardware y sistema operativo) particular. ; un lenguaje interpretado por otro lado no tiene, en principio, esta dependencia pero es más lento y requiere más memoria en tiempo de ejecución.

Código de bytes y código P

Una solución intermedia entre la compilación y la interpretación se introdujo en las primeras versiones de Pascal (incluida la creada en 1975 por su inventor, Niklaus Wirth ) y posteriormente se adoptó en los lenguajes Java y Python , con bytecode , y en Visual Basic y .NET. lenguajes de Microsoft con el código P.

En ambos casos el código fuente de los programas no se compila en lenguaje máquina, sino en un código intermedio "híbrido" destinado a ser interpretado en el momento de la ejecución del programa: la razón de este doble paso es tener la portabilidad de interpretado idiomas, sino también, gracias a la precompilación, una fase de interpretación más simple y, por lo tanto, más rápida. En el caso del código de bytes de Java, estamos tratando con un lenguaje ensamblador real , que originalmente tuvo que implementarse en un modelo de procesador real, pero nunca se realizó; algunos microprocesadores modernos, como ARM con Jazelle , implementan de forma nativa muchas instrucciones de código de bytes y, por lo tanto, pueden ejecutar el código de bytes de Java como si fuera un ensamblaje.

Sin embargo, el código intermedio es más fácil tanto de interpretar como de compilar: por ello se han desarrollado compiladores JIT (Just In Time) tanto para lenguajes Java como .NET, que al momento de lanzar un programa Java o .NET compilan código intermedio sobre la marcha y ejecutar código de máquina nativo, eliminando por completo la necesidad de un intérprete y haciendo que los programas escritos en estos lenguajes sean casi tan rápidos como sus programas compilados.

Entornos de desarrollo y ejecución

Con entorno de desarrollo entendemos el conjunto de herramientas para el desarrollo del código fuente del programa , mientras que con entorno de ejecución normalmente nos referimos al conjunto de bibliotecas de software , también denominadas plataforma de software , utilizadas por el propio programa para funcionar correctamente.

Clases de idiomas

En general, existen unos 2500 lenguajes de programación más o menos conocidos y extendidos. Estos se clasifican en primer lugar, según el nivel de abstracción, desde el lenguaje máquina hasta el lenguaje lógico humano, en lenguajes de bajo y alto nivel (en los años noventa se distinguían incluso los de más alto nivel ). A su vez, los lenguajes se pueden clasificar en lenguajes compilados e interpretados como se vio anteriormente. Los lenguajes se suelen dividir entonces en tres grandes familias en base al paradigma de programación de referencia : lenguajes imperativos , funcionales y lógicos .

Imperativos

En los lenguajes imperativos, la instrucción es un comando explícito, que opera sobre una o más variables o sobre el estado interno de la máquina, y las instrucciones se ejecutan en un orden predeterminado. Escribir un programa en un lenguaje imperativo esencialmente significa lidiar con lo que la máquina tiene que hacer para obtener el resultado que deseas, y el programador está ocupado ajustando los algoritmos necesarios para manipular los datos. Las estructuras de control adoptan la forma de sentencias de flujo (GOTO, FOR, IF / THEN / ELSE, etc.) y el cálculo procede por iteración en lugar de por recursión. Los valores de las variables a menudo se asignan a partir de constantes u otras variables (asignación) y rara vez pasando parámetros (instanciación).

Idiomas imperativos típicos:

Estructurado

La programación estructurada es una técnica cuyo propósito es limitar la complejidad de la estructura de control del programa. El programador está obligado a utilizar únicamente las estructuras de control canónicas definidas por el Teorema de Böhm-Jacopini , es decir la secuencia , la selección y el bucle , evitando las instrucciones de salto incondicional.

Orientado a objetos

La programación orientada a objetos se basa en una evolución del concepto de tipo de datos abstracto caracterizado por encapsulación , herencia , polimorfismo . Además de los lenguajes especializados que implementan completamente los principios de esta metodología (como Smalltalk o Java), muchos lenguajes modernos incorporan algunos conceptos de programación orientada a objetos.

Funcional

Los lenguajes funcionales se basan en el concepto matemático de función. En un lenguaje funcional puro, la asignación explícita incluso está completamente ausente y solo se usa el paso de parámetros. Normalmente, en este modelo, el control del cálculo se gestiona mediante la recursión y la coincidencia de patrones (la acción de verificar la presencia de un determinado motivo - patrón - dentro de un objeto compuesto), mientras que la estructura de datos más común es la lista , una secuencia de elementos. . El exponente más importante de esta categoría es sin duda Lisp (LISt Processing).

Declarativo (o lógico)

En los lenguajes lógicos, la instrucción es una cláusula que describe una relación entre datos: programar en un lenguaje lógico significa describir el conjunto de relaciones existentes entre los datos y el resultado deseado, y el programador se ocupa de establecer cómo deben evolucionar los datos durante el cálculo. . No hay un orden preestablecido de ejecución de las diversas cláusulas, pero depende del intérprete encontrar el orden correcto. La estructura de control principal está representada por el corte , que se denomina rojo si modifica el comportamiento del programa o verde si solo hace más eficiente el cálculo, que procede por recursión y no por iteración. Las variables reciben su valor por instanciación o de otras variables ya asignadas en la cláusula ( unificación ) y casi nunca por asignación, que se utiliza sólo en el caso de cálculo directo de expresiones numéricas.

Para que puedan usarse en un programa declarativo, todos los algoritmos normales deben reformularse en términos recursivos y de retroceso ; esto hace que programar con estos lenguajes sea una experiencia completamente nueva y requiere una forma de pensar radicalmente diferente, porque más que calcular un resultado, requiere demostrar su valor exacto. Ante estas exigencias, los lenguajes declarativos permiten lograr resultados excepcionales a la hora de manipular grupos de entidades en relación entre sí.

Lenguajes débilmente o fuertemente tipados

Otra clasificación quiere desde el punto de vista del tipo de datos expresados, quiere la subdivisión en idiomas con tipeo fuerte o tipeo débil.

Lenguajes esotéricos

Idiomas paralelos

Las supercomputadoras modernas y, por ahora, todas las computadoras de gama alta y media están equipadas con múltiples CPU . Como consecuencia obvia, esto requiere la capacidad de explotarlos; por eso primero se desarrolló el multithreading , es decir, la capacidad de lanzar varias partes de un mismo programa al mismo tiempo en diferentes CPUs, y luego se estudiaron algunos lenguajes de tal forma que se pudieran identificar por sí mismos, durante el fase de compilación, las partes del código que se lanzarán en paralelo.

Lenguajes de script

Los lenguajes de scripting nacieron como lenguajes por lotes , para automatizar tareas largas y repetitivas a realizar, de hecho, en modo por lotes . En lugar de escribir los comandos uno por uno para realizar una determinada tarea, se guardan en secuencia en un archivo, que a su vez puede usarse como un comando compuesto. Los primeros lenguajes de scripting fueron los de los shells de Unix ; posteriormente, dada la utilidad del concepto, muchos otros programas interactivos han comenzado a permitir guardar y ejecutar archivos que contienen listas de comandos, o guardar grabaciones de comandos visuales (las llamadas macros de los procesadores de texto , por ejemplo) . El siguiente paso, en muchos casos, ha sido la extensión de los lenguajes con la asociación de símbolos a valores, es decir, el uso de variables, con comandos de gestión de flujo, es decir, construcciones de salto condicional, instrucciones de bucle o de recursividad, haciéndolos así completos. idiomas Recientemente, muchos programas nacidos con fines muy distintos a la programación ofrecen a los usuarios la posibilidad de programarlos de forma autónoma utilizando lenguajes de scripting.

La sintaxis de muchos lenguajes de secuencias de comandos, como PHP o los dialectos de ECMAScript , es similar a la de C, mientras que otros, como Perl o Python , adoptan un nuevo diseño. Dado que muy a menudo los lenguajes de scripting nacen para la invocación de comandos o procedimientos externos, al igual que muchas veces son interpretados , es decir, ejecutados por otro programa, como el programa madre, del cual el lenguaje de scripting es una extensión, o un intérprete apropiado. .

Otros idiomas

Otro tipo de lenguajes son lenguajes de programación de muy alto nivel utilizados por profesionales y lenguajes de programación visuales que no requieren conocimientos especiales de programación avanzada.

Evaluación

En general, no tiene sentido hablar de lenguas mejores o peores, o de las mejores lenguas de todas: toda lengua nace para enfrentarse a una clase de problemas más o menos amplia, de una forma determinada y en un contexto determinado. Sin embargo, al tener que decir si un idioma dado es adecuado para un uso determinado o no, es necesario evaluar las características de los distintos idiomas.

Características intrínsecas

Son las cualidades del lenguaje mismo, determinadas por su sintaxis y su arquitectura interna. Afectan directamente al trabajo del programador, condicionándolo. No dependen de las herramientas utilizadas (compilador/intérprete, IDE, enlazador) ni del sistema operativo o tipo de máquina.

A veces, un programa muy complejo y difícilmente legible en un idioma determinado puede volverse absolutamente simple y directo si se reescribe en un idioma de clase diferente y más adecuado.

El ejemplo más común de lenguaje robusto es Pascal, que al haber sido creado con fines didácticos siempre asume que una irregularidad en el código es el resultado de un error del programador; mientras que assembly es el ejemplo por excelencia de un lenguaje totalmente libre, en el que nada ata al programador (y si escribe código peligroso o incorrecto, no hay nada que le advierta).

Características externas

Además de las cualidades mencionadas de las lenguas, se pueden examinar las de los entornos en los que operan. Un programador trabaja con herramientas de software, cuya calidad y productividad depende de un conjunto de factores que también deben sopesarse según el tipo de programas a escribir.

Notas

  1. ^ Robert W. Sebesta, Conceptos de lenguajes de programación , 2006, págs. 44. ISBN 0-321-33025-0
  2. ^ Sitio web de TIOBE Software que elabora mensualmente un ranking de popularidad de lenguajes de programación .

Bibliografía

Artículos relacionados

Otros proyectos

Enlaces externos