Download lenguajes de programación - E

Document related concepts
Transcript
LENGUAJES DE
PROGRAMACIÓN
POO
Nombre: Guillermo Aedo Contreras
Profesor: Fernando Guerrero
Curso
: Laboratorio de Aplicaciones
Computacionales.
1
Introducción



Al desarrollarse las primeras computadoras electrónicas, se vio
la necesidad de programarlas, es decir, de almacenar en
memoria la información sobre la tarea que iban a ejecutar. Las
primeras se usaban como calculadoras simples; se les
indicaban los pasos de cálculo, uno por uno.
Hay una variedad de lenguajes de programación como por
ejemplo c/c++, java, Cobol, etc.
Ahora los invito a navegar por el mundo de los lenguajes de
programación.
2
¿Porqué estudiar lenguajes de
programación?

La pregunta es ¿cuál es la ventaja de estudiar una
variedad de lenguajes diferentes que es poco
probable que uno llegue a utilizar?:
 Mejorar
la habilidad para desarrollar algoritmos eficaces.
 Mejorar el uso del lenguaje de programación disponible.
 Acrecentar el propio vocabulario con construcciones
útiles sobre programación.
 Hacer posible una mejor elección del lenguaje de
programación.
 Facilitar el aprendizaje de un nuevo lenguaje.
 Facilitar el diseño de un nuevo lenguaje.
3
Breve historia de los lenguajes
de programación:

Desarrollo de los primeros lenguajes:
 Lenguajes
basados en el cálculo numérico
(Ejemplo: FORTRAN).
 Lenguajes para negocios (Ejemplo:
COBOL).
 Lenguajes para Inteligencia Artificial
(Ejemplo: LISP).
 Lenguajes para sistemas (Ejemplo: C).
4
Evolución de los
Lenguajes de Programación
Declarativos
5
Evolución de los
Lenguajes de Programación
Orientados a Objetos e
Imperativos
6
El papel de los lenguajes de
programación

Inicialmente los lenguajes se proyectaban para ejecutar programas con
eficiencia. A mediados de los años sesenta la programación cambia:

Las máquinas son menos costosas y aumentan los costos de programación.
 Surge la necesidad de trasladar programas de unos sistemas a otros.
 El mantenimiento del producto consume mayores recursos de cómputo.
 La tarea del lenguaje de alto nivel es la de facilitar el desarrollo de programas
correctos para resolver problemas en alguna área de aplicación dada.

Los lenguajes de programación evolucionan o dejan de usarse.
Influencias que obligan a la revisión del los lenguajes:






Capacidad de las computadoras.
Aplicaciones: Los requerimientos de nuevas áreas de aplicación afectan los
diseños de nuevos lenguajes y las revisiones y ampliaciones de los más
antiguos.
Métodos de programación.
Métodos de implementación.
Estudios teóricos.
Estandarización.
7
Atributos de un buen lenguaje








Claridad, sencillez y unidad (legibilidad): La sintaxis del lenguaje afecta la
facilidad con la que un programa se puede escribir, por a prueba, y más tarde
entender y modificar.
Ortogonalidad: Capacidad para combinar varias características de un lenguaje en
todas las combinaciones posibles, de manera que todas ellas tengan significado.
Naturalidad para la aplicación: La sintaxis del programa debe permitir que la
estructura del programa refleje la estructura lógica subyacente.
Apoyo para la abstracción: Una parte importante de la tarea del programador es
proyectar las abstracciones adecuadas para la solución del problema y luego
implementar esas abstracciones empleando las capacidades más primitivas que
provee el lenguaje de programación mismo.
Facilidad para verificar programas: La sencillez de la estructura semántica y
sintáctica ayuda a simplificar la verificación de programas.
Entorno de programación: Facilita el trabajo con un lenguaje técnicamente débil
en comparación con un lenguaje más fuerte con poco apoyo externo.
Portabilidad de programas
Costo de uso:




1. Costo de ejecución del programa.
2. Costo de traducción de programas.
3. Costo de creación, prueba y uso de programas.
4. Costo de mantenimiento de los programas: costo total del ciclo de vida.
8

Dominios
de
aplicación
Aplicaciones de los años sesenta. Durante la década de 1960, casi
toda la programación se podía dividir en cuatro modelos básicos de
programación:





De procesamiento de negocios (COBOL).
Científicos (FORTRAN).
De sistemas (ALGOL, JOVIAL, etc.): Para construir sistemas operativos.
De Inteligencia Artificial (LISP).
Aplicaciones de los años noventa. La situación actual tiene más
dominios de aplicación:





De procesamiento de negocios (COBOL).
Científicos (FORTRAN 90).
De sistemas: Con el advenimiento de los microprocesadores baratos que
gobiernan automóviles, hornos de microondas, etc., ha aumentado la
necesidad de contar con lenguajes para tiempo real.
Edición: Los sistemas de procesamiento de texto tienen su propia sintaxis
para mandatos de entrada y archivos de salida. El traductor TEX produce un
programa en el lenguaje PostScript de descripción de páginas. PostScript se
puede compilar por medir de un procesador adecuado. Éste suele ser la
impresora láser que se utiliza para imprimir el documento.
De proceso: Dentro de UNIX, el lenguaje de comandos de usuario se conoce
como shell y a los programas se les llama guiones de shell (parecidos a los
archivos .bat). Estos guiones se pueden invocar siempre que ocurren ciertas
9
condiciones habilitadoras.
Estandarización de los lenguajes

Los estándares son en general de dos clases:



1. Estándares patentados (DE PACTO): Son las definiciones
elaboradas por la compañía que desarrollo el lenguaje y que es su
propietaria.
2. Estándares de consenso (DE FACTO): Se trata de documentos
elaborados por organizaciones con base en un acuerdo entre los
participantes pertinentes. Método principal para asegurar la
uniformidad entre varias implementaciones de un lenguaje. Ejemplo:
ANSI, IEEE, ISO, etc..
Proceso en el desarrollo de normas: Un grupo decide
que un lenguaje requiere una definición estándar. El
organismo normativo organiza un grupo de trabajo de
voluntarios para desarrollar esa norma. Cuando el grupo de
trabajo llega a un acuerdo sobre su norma, se somete a
votación por parte de un bloque más grande de individuos
interesados. Los desacuerdos se resuelven y se produce el
estándar del lenguaje.
10
Uso de estándares en forma eficaz

Es necesario ocuparse de tres cuestiones:

Oportunidad (¿Cuándo estandarizar un lenguaje?): Lo deseable sería
estandarizar un lenguaje lo suficientemente pronto para que exista
suficiente experiencia en el uso del lenguaje, pero no demasiado tarde,
para no alentar muchas implementaciones incompatibles.
 Conformidad (¿Qué significa que un programa se adhiere a un estándar y
que un compilador compila un estándar?): Si existe un estándar para un
lenguaje, se suele hablar de conformidad con respecto a ese estándar. Un
programa es conforme si sólo utiliza características definidas en el
estándar. Un compilador conformable es uno que, cuando se le da un
programa conforme, produce un programa ejecutable que genera la salida
correcta.
 Obsolescencia (¿Cuándo envejece un estándar y cómo se modifica?): Los
estándares se tienen que revisar cada 5 años y ya sea renovarse o
descartarse. Casi todos los estándares requieren compatibilidad hacia
atrás; El nuevo estándar debe incluir versiones más antiguas del lenguaje.
Esto tiene el problema de que el lenguaje se puede hacer difícil de manejar
a causa de las numerosas construcciones obsoletas.
Una característica es obsolescente si es candidata a ser descartada en la
próxima versión del estándar.
Una característica desaprobada se puede volver obsolescente en el
próximo estándar, por lo cual puede ser descartada después de dos
revisiones.
11
Efectos de los entornos sobre
los lenguajes

Cuatro clases generales de entornos objetivo
cubre casi todas las aplicaciones de
programación:
 de
procesamiento por lotes,
 interactivo,
 de sistema empotrado, y
 de programación (entorno interactivo).
Cada uno plantea distintos requerimientos
sobre los lenguajes adaptados a esos
entornos.
12
Entornos de procesamiento por
lotes

El más simple entorno operativo se compone sólo de
archivos externos de datos. Un programa toma un cierto
conjunto de archivos de datos como entrada, procesa los
datos y produce un conjunto de archivos de datos de salida.
El nombre de procesamiento por lotes viene porque los
datos de entrada se reúnen en “lotes” de archivos y son
procesados en lotes por programas.



Los archivos constituyen la base para casi toda la estructura de E/S.
Un error que termine la ejecución del programa es aceptable aunque
costoso. No es posible la ayuda externa por parte del usuario para
manejar o corregir errores de inmediato.
Carencia de restricciones de regulación de tiempo. No hay recursos
para monitorear o afectar directamente la velocidad de ejecución del
programa.
13
Entornos interactivos

El programa interactúa durante su ejecución directa con un
usuario en una consola de visualización, enviando
alternativamente salidas hacia ésta y recibiendo entradas
desde el teclado o ratón (procesadores de texto, hojas de
cálculo, juegos, etc.).




Las características de E/S interactivas son diferentes de las
operaciones ordinarias con archivos.
El programa debe ser capaz de gestionar el manejo de errores. La
terminación del programa como respuesta aun error no es
ordinariamente aceptable (a diferencia del procesamiento por lotes).
Los programas interactivos deben utilizar con frecuencia algún
concepto de restricciones de tiempo.
El concepto de programa principal suele estar ausente. En su lugar,
el programa se compone de un conjunto de subprogramas y el
usuario introduce el “programa principal como una serie de
comandos en el terminal.
14
Entornos de sistemas incrustados (empotrados)

Un sistema de computadora que se usa para controlar parte de
un sistema más grande como una planta industrial, una
aeronave, etc., se conoce con el nombre de sistema de
computadora incrustado. El fallo de una aplicación empotrada
puede poner en peligro la vida. La seguridad de
funcionamiento y corrección son atributos principales.





Suelen operar sin un sistema operativo subyacente y sin archivos de
entorno y dispositivos de E/S usuales. El programa debe interactuar
directamente con la máquina.
El manejo de errores tiene gran importancia. Cada programa debe estar
preparado para manejar todos los errores en forma interna, adoptando
acciones apropiadas para recuperarse y continuar. La interrupción del
programa no es aceptable y no hay un usuario en el entorno que pueda
proporcionar la corrección interactiva del error.
Operan en tiempo real, donde la respuesta las entradas debe producirse
en intervalos de tiempo restringidos.
Suele ser un sistema distribuido, compuesto por más de una
computadora.
Una vez iniciadas las tareas, se ejecutan por lo común de forma
15
simultánea e indefinida.
Entornos de programación


Es el entorno en el cual los programas se crean y se ponen a prueba. Consiste en
un conjunto de herramientas (editor, depurador, verificador, generadores de datos
de prueba, etc.) de apoyo y un lenguaje para invocarlas.
Al compilar por separado cada subprograma el compilador necesita información
de:




La especificación del número, orden y tipo de parámetros.
La declaración de tipo de datos.
La definición de un tipo de datos (para la declaración local de variables).
Un problema común, es encontrar, durante el ensamblado del programa final
completo, que varios subprogramas y otras unidades de programa tienen
nombres (de variables) iguales. Métodos para evitar este problema:
Todo nombre compartido debe ser único. Se deben usar convenciones para la
asignación de nombres desde un principio.
2. Definir, en el lenguaje, reglas de ámbito, para ocultar nombre.
3. Los nombres se pueden conocer agregando explícitamente sus definiciones desde una
biblioteca externa (herencia en POO).
1.

Características que ayudan a poner a prueba y depurar programas.
Características para rastreo de ejecución.
Puntos de interrupción. Cuando se alcanza un punto de interrupción durante la
ejecución del programa, la misma se interrumpe y el control se traslada al programador
en un terminal.
3. Asertos: expresan relaciones que deben cumplirse entre los valores de las variables en
ese punto del programa.
1.
2.
16
Marcos de ambiente

Un ambiente de apoyo
consiste en servicios
de infraestructura que
se conocen como
marco de ambiente.
Este marco suministra
servicios como un
depósito de datos,
interfaz gráfica de
usuario, seguridad y
servicios de
comunicación. Los
programas se escriben
de modo que utilicen
estos servicios.
17
Máquinas virtuales

Aunque hay muchos rasgos que se podrían destacar
como candidatos para formar parte de una definición del
concepto de máquina virtual (a partir de ahora MV), una
MV se puede definir sencillamente como una capa de
abstracción que separa el funcionamiento de un
ordenador de su hardware. Además, las MV se dividen
en abstractas o teóricas, como sería la máquina de
Turing (el primer ejemplo de una MV), y concretas o
prácticas (a las que se quiere normalmente se hace
referencia al hablar de MV). En esta sección se tratarán
las MV concretas que, como se verá, son capas de
software que juegan un papel relevante tanto en el
funcionamiento de los lenguajes compilados como
interpretados.
18
Introducción al concepto


Las MV se construyeron para simplificar el
proceso del control del hardware de un
ordenador porque extienden y enmascaran la
funcionalidad del hardware a través de
procedimientos y datos abstractos.
Se pueden identificar dos tipos de MV
concretas:
 las
que juegan un papel en la preparación de un
programa para su ejecución (tiempo de compilación)
y
 las que permiten la ejecución de dicho programa. La
figura muestra la diferencia entre los dos tipos:
19
El papel de las máquinas virtuales en la compilación y la ejecución de un programa.
20
Introducción al concepto

Las MV suelen aparecer en una jerarquía. Usamos la jerarquía de MV de
compilación, por ejemplo, cada vez que invocamos el compilador de
C++. Y dos ejemplos muy comunes del papel de una MV en la jerarquía
de MV de ejecución son PostScript (que define una MV para una
impresora) y MSDOS bajo MS Windows (que define una MV que permite
que antiguos programas de DOS funcionen bajo Windows).


PostScript es una MV que incluye el estado gráfico, la ruta actual, el estado
del diccionario y, aunque sea bastante complejo, presenta una visión de alto
nivel de muchos tipos distintos de impresoras, aislando las características de
las impresoras de las aplicaciones que las usan.
A la hora de implementar un lenguaje de programación, las estructuras
de datos y algoritmos utilizados en la ejecución de un programa (es
decir, la sintaxis y semántica de cada estructura) definen las MV
(implícitamente) para este lenguaje. Y las decisiones que toma el
desarrollador afectan tanto a la traducción como a la ejecución de los
programas escritos en este lenguaje. Las MV se distinguen entre sí
según tres criterios:
•La concepción de las MV que tiene el desarrollador basada en la definición
del lenguaje.
 •Las facilidades disponibles en el hardware del ordenador.
 •Las decisiones de implementación tomadas por los desarrolladores.

21
Introducción al concepto

Aunque se puede escribir un compilador para traducir (o compilar) un
programa escrito en un lenguaje de alto nivel directamente al código
máquina (en el sentido de no depender de ninguna otra pieza en el
sistema para producirlo), no es nada común hacerlo hoy en día por varias
razones, dos de las cuales son:

Cuando aparezca en el mercado el siguiente procesador (por ejemplo,
Pentium IVdespués de Pentium III), habrá que modificar el compilador.
 No tiene sentido repetir el proceso de diseño y desarrollo, que es costoso,
cuando ya se ha hecho lo mismo muchas veces antes para otros lenguajes
para una máquina concreta.

Un caso lo constituyen los compiladores C, que ya llevan mucho tiempo en
funcionamiento y son muy eficientes y estables. Por lo tanto, hay varios
lenguajes como C++ (al menos en las primeras versiones) cuyo
“compilador” tradujo el código fuente de C++ a C para poder luego usar el
compilador C estándar. En general, sólo se suele rediseñar un compilador
nuevo desde cero cuando los ingenieros del lenguaje están intentando
alcanzar nuevos objetivos para ese lenguaje, en caso de que vayan más
allá que el modelo funcional de los compiladores ya disponibles como, por
ejemplo, es el caso de Java.
22
Jerarquías de máquinas virtuales


La realidad es que el desarrollador de un lenguaje suele implementar las MV (de
compilación y/o ejecución) de su lenguaje en términos de otras MV ya existentes. Y en el
futuro, un programador de aplicaciones utilizará las MV implementadas por el
desarrollador del lenguaje para producir programas que a su vez puedan servir como MV
para otras aplicaciones, etc. La conclusión, como puede verse, es que una MV no suele
existir aislada, sino como parte de una jerarquía de MV. A continuación se va a ver el
papel de las jerarquías de MV en el tiempo de compilación y de ejecución.
En primer lugar, se va a considerar el papel de la jerarquía de MV en el tiempo de
compilación. En el caso de C++, como lenguaje de alto nivel que se compila a un
lenguaje tan cerca del nivel de máquina como sea posible, se puede ver que el proceso
de compilación de un programa de C++ consiste en la interacción de la jerarquía de MV
mostrada en la figura 2 (aunque puede haber diferencias entre compiladores de C++; por
ejemplo, aquí se supone que es un proceso de compilación que usa C como código
intermedio). El pre-procesador acepta el código C++ como fuente y produce otra versión
del mismo código C++ con algunas extensiones e incorporaciones resueltas. El traductor
convierte el código fuente C++ estándar a código fuente C. El compilador C acepta este
código como fuente y lo traduce a código ensamblador (una representación simbólica del
código máquina). El ensamblador traduce este código simbólico a un código máquina
reubicable. Y por fin, el cargador de librerías acepta este código máquina como entrada y
produce un programa simple ejecutable, compuesto por el código máquina de entrada y
todos los subprogramas necesarios con direcciones de memoria contiguas. Además del
proceso de compilación, la traducción completa de los programas de alto nivel (previa a
su ejecución) en una forma que corre sobre la máquina, también existe otro proceso, que
se llama interpretación, que tiene más que ver con el papel de las MV en el tiempo de
ejecución que en el tiempo de compilación.
23
Jerarquías de máquinas virtuales


Además
de
los
lenguajes
compilados
“completamente”, hay otros que son compilados
“parcialmente” en el sentido de que terminan el
proceso de compilación en un código (o lenguaje)
intermedio, en vez de en código máquina (lenguajes
intermedios).
En segundo lugar, vamos a considerar el papel de la
jerarquía de MV en el tiempo de ejecución. Se puede
ver un ejemplo en la figura 3. Como se puede ver en
él, lo que se podría llamar una aplicación Web (unas
páginas Web con elementos interactivos incrustados)
está escrita en HTML y funciona sobre una MV dada
por el navegador Web, que a su vez está
implementado en C o C++. Éste corre sobre una MV
compuesta por las librerías de tiempo de ejecución
que encapsulan el funcionamiento de los
procedimientos (o métodos) y datos de navegador
Web que, a su vez, utilizan las funciones de la MV
del sistema operativo implementadas en código
máquina. Y los programas que componen esta MV
corren sobre el firmware, un conjunto de programas
de micro-código que controlan directamente el
hardware del ordenador.
24
Jerarquías de máquinas virtuales


Las jerarquías del tipo mostrado en la figura
tienen una estructura muy parecida a una
jerarquía “usa”, donde cada capa usa la capa
que está directamente debajo. La diferencia es
que una MV puede tener una interfaz hacia
abajo, además de la interfaz hacia arriba, que
especifica los servicios que requiere de la capa
inferior, pero sin especificar exactamente qué
implementación de los servicios es necesario.
Un ejemplo sería la jerarquía de MV que
compone el sistema de ventanas X, donde hay
una capa que define el funcionamiento
independientemente de los dispositivos y,
directamente debajo, una capa que define el
funcionamiento en términos de los dispositivos.
Aquí X depende de la capa que depende de los
dispositivos, no de una implementación en
concreto de esta capa (por lo tanto, hay
versiones de X para muchos tipos de hardware
donde la única diferencia es la implementación
de la capa relacionada con los dispositivos; las
demás capas superiores son idénticas).
25
Lenguajes intermedios

Un lenguaje intermedio se puede definir
como
una
manera
de
representar
procedimientos y estructuras de datos que
sirva como entrada para una MV en alguna
parte de su jerarquía, entre el lenguaje de
entrada (el nivel más alto) y el código
ejecutado en la máquina (el nivel más bajo)
tanto en el tiempo de compilación como en el
de ejecución.
26
Lenguajes intermedios

Para considerar el papel de los lenguajes intermedios y sus
ventajas y desventajas, conviene destacar la diferencia entre
la traducción de un lenguaje de alto nivel a código máquina
anteriormente a su ejecución (su compilación) y su
interpretación, es decir, la conversión de cada instrucción del
lenguaje a código máquina y su ejecución, una por una, al
ejecutar el programa. Este proceso se realiza a través de
una MV de interpretación que simula un ordenador cuyo
código máquina es el lenguaje de alto nivel que está siendo
interpretado. Y típicamente, esta MV se construye a través
de un conjunto de programas de código máquina que
representa los algoritmos y estructuras de datos necesarios
para la ejecución de las instrucciones del lenguaje de alto
nivel. Hay ventajas y desventajas en cada manera de
convertir los lenguajes de alto nivel a código máquina, que
se pueden resumir así:
27
Lenguajes intermedios
28
Lenguajes intermedios


Estos dos casos representan los dos extremos
porque, como ya se ha visto, existe también lo que
se llama la compilación parcial, que es una mezcla
de los dos enfoques, donde se compila el lenguaje
de alto nivel a un lenguaje intermedio (más cerca
de las estructuras presentes en el código máquina
que las del código fuente) y luego se interpreta este
lenguaje al ejecutar el programa.
Como puede imaginarse, esta técnica combina las
ventajas y desventajas de los dos enfoques
anteriores. Un ejemplo de esta combinación existe
en el lenguaje de programación Java y su entorno.
29
Lenguajes intermedios



Entre otras cosas, Java empezó con la idea de liberar al
programador de las dificultades de portar su aplicación a
nuevas plataformas lo cual, si el programa está muy
vinculado a algún aspecto del sistema operativo donde fue
escrito, podría ser muy difícil.
Se compilará el código fuente de Java a un código byte
(bytecode) antes de ejecutarlo. Y a la hora de correr el
programa, este código, como lenguaje intermedio, sería el
lenguaje de entrada para una MV, que con un conjunto de
librerías (el entorno de ejecución de Java, Java Runtime o
JRE), la interpretaría para su ejecución.
Por lo tanto, este bytecode podría correr en cualquier
hardware donde haya una versión del JRE disponible. Como
este bytecode está más cerca del nivel de máquina que de
un lenguaje de alto nivel, los programas correrán más
rápidamente
que
los
programas
completamente
interpretados, aunque más despacio que los programas
previamente compilados al código máquina.
30
Lenguajes intermedios

Como se puede ver en la figura 1, tanto los
programas compilados parcialmente a un
lenguaje intermedio (como Java) como los
programas escritos en lenguajes de alto nivel
que se interpretan (como Lisp) requieren una
MV para interpretar el programa. La principal
ventaja del lenguaje intermedio en este caso
es su proximidad al nivel del código máquina,
en el sentido de que supone menos trabajo a
la hora de ejecutarlo y, por lo tanto, los
programas corren más rápidamente que los
puramente interpretados.
31
Lenguajes intermedios

Además del papel de los lenguajes
intermedios en la compilación parcial, se
puede destacar su papel en la compilación
estándar. Como ejemplo se puede considerar
C como lenguaje intermedio para un lenguaje
compilado nuevo. Si el autor de un nuevo
lenguaje decide utilizar C, por ejemplo, como
su lenguaje intermedio, sólo tendrá que
implementar una MV para convertir el código
fuente de su lenguaje a C, ahorrando mucho
trabajo.
32
Lenguajes intermedios

Las ventajas de utilizar un lenguaje tan establecido
como C como lenguaje intermedio son:
 •La
facilidad de portar el lenguaje a una nueva máquina
(sólo hay que tener un compilador C disponible allí).
 •La generación de código máquina es una tarea muy
compleja que requiere un conocimiento profundo de la
arquitectura de la máquina en cuestión – y de cada
máquina en que se quiere una versión del lenguaje.
 •La facilidad de modificar algún rasgo del comportamiento
del lenguaje en alguna máquina en concreto (por ejemplo,
características de memoria o rendimiento – se pueden
añadir librerías C customizadas sin grandes problemas).
 •Las posibilidades disponibles para mapear estructuras
intermedias del nuevo lenguaje a estructuras de datos de
C.
33
Lenguajes intermedios

Y las desventajas son:
 •La
depuración es muy difícil porque, entre otras cosas, los
errores que ocurren en el código C no son muy fáciles de
localizar en lo que ha escrito el programador originalmente
en el nuevo lenguaje.
 •Las características de rendimiento y eficiencia del
lenguaje están determinadas por el
 compilador C.
 •Habrá ocasiones en las que no exista una buena
traducción entre una estructura en el nuevo lenguaje y las
estructuras de datos en C, por lo que habrá una pérdida de
eficiencia en el programa resultante (como, por ejemplo,
ocurre en la mayoría de las ocasiones en que se compilan
estructuras de Prolog a C – sólo se puede expresar
iteración en Prolog utilizando recursión).
34
La máquina virtual de Java como
ejemplo de una MV


La MV de Java es una máquina de pila. Las instrucciones
interpretadas por ella manipulan datos almacenados como
elementos en una pila. El contenido ejecutable de un archivo
de bytecodes contiene un vector de instrucciones bytecode
para cada método. Los bytecodes son instrucciones para la
MV, que tiene algunos registros de variables locales y una
pila para la evaluación de expresiones.
Las primeras variables locales son inicializadas con los
parámetros actuales. Cada variable local o elemento de la
pila es una palabra que corresponde a un entero de 32 bits,
a un punto flotante o a una referencia a objeto (puntero).
Para puntos flotantes dobles y enteros largos se utilizan dos
huecos de la pila.
35
La máquina virtual de Java como
ejemplo de una MV


Los huecos de la pila no están relacionados con un tipo de
datos, es decir, en algún punto un hueco podría contener un
valor entero y en otro, el mismo hueco podría contener una
referencia a un objeto. Sin embargo, no se puede almacenar
un entero en un hueco y luego recuperarlo reinterpretándolo
como si fuera una referencia a un objeto. Aún más, en
cualquier punto del programa, el contenido de cada hueco
está asociado con un único tipo de datos que puede ser
determinado usando un flujo estático de datos.
El tipo de datos podría ser “no asignado”, con lo cual no se
permite leer el valor del hueco. Estas restricciones son parte
del modelo de seguridad de Java y se ven reforzadas por el
verificador de bytecodes.
36
La máquina virtual de Java como
ejemplo de una MV


El código interpretado es generalmente más lento
que un programa escrito en un lenguaje compilado, y
Java no es distinto en este aspecto. Se han señalado
muchas posibilidades para mejorar el rendimiento de
los intérpretes.
Una muy común hoy en día es incluir un compilador
relativamente simple en el tiempo de ejecución de la
MV. Es decir, en vez de interpretar los bytecodes del
programa una y otra vez, se compilan una sola vez
“al instante” en el interior de la MV, y la
representación compilada de los métodos que
corresponden al programa es ejecutada al efectuar
una llamada. Esto es conocido como un compilador
al instante (o JIT, Just In Time).
37
“Sintaxis y Semántica de los
Lenguajes de Programación”
38
PARADIGMAS DE PROGRAMACIÓN

La clasificación de los lenguajes atendiendo a sus
características intrínsecas conduce a los llamados
paradigmas de programación. Un paradigma de
programación es un modelo de programación que
engloba a ciertos lenguajes que comparten:


Elementos estructurales: ¿con qué se confeccionan los
programas?
Elementos metodológicos: ¿cómo se confecciona un programa?
39
Programación Imperativa o
Procedural: FORTRAN


Es la primera que se desarrolla porque va determinando
las operaciones que hay que realizar sobre una máquina
ideal de Von Neumann. Desde este punto de vista un
programa es una secuencia de acciones (instrucciones)
que se realizan en un cierto orden determinado por el
flujo del programa.
Las estructuras para el control son generalmente
sentencias condicionales y bucles. Como un ejemplo
ilustrativo veamos el aspecto de un programa en
lenguaje Pascal que calcula el factorial de un número
positivo x:
40
FORTRAN. Historia
Primer lenguaje de alto nivel (1957).
 Desarrollado por IBM para el IBM 704.
 Estaba orientado a la eficiencia en la
ejecución.
 Definición estándar del lenguaje en el 66.
 Otras versiones:

 FORTRAN
77
 FORTRAN 90
41
FORTRAN. Ejemplo
PROGRAM TRIVIAL
INTEGER I
I=2
IF(I .GE. 2) CALL PRINTIT
STOP
END
SUBROUTINE PRINTIT
PRINT *,’Hola Mundo’
RETURN
END
42
FORTRAN. Características
Tipos de datos:
 Numéricos
(enteros, reales, complejos y doble
precisión).
 Booleanos (logical)
 Arreglos
 Cadenas de caracteres
 Archivos


FORTRAN 90 ya es estructurado, y no requiere
sentencias GOTO.
Sólo dos ámbitos para las variables: local y
global
43
Ejemplo anotado
44
FORTRAN. Objetos de datos
Variables y constantes





FORTRAN no es sensible a mayúsculas y minúsculas. Los
nombre de variables tienen de 6 a 31 caracteres máximo y
deben comenzar por una letra. Los blancos son
significativos.
Declaración explicita de variables.
Enteras (I-N), el resto reales. (se modifica con IMPLICIT).
Punteros: en los primeros FORTRAN no hay punteros y
todas las variables se almacenan en memoria estática. En
FORTRAN 90 se declaran INTEGER, POINTER::P.
Para memoria dinámica ALLOCATE y DEALLOCATE
45
FORTRAN. Objetos de datos
Tipos de datos estructurados

Arrays, pueden tener hasta 7 dimensiones y se guardan por
colummnas.

REAL M(20),N(-5:5)
 DIMENSION I(20,20) (tipo por nomenclatura implícita)

Cadenas de caracteres, el primer carácter es el 1, el operador //
permite concatenar cadenas.


Almacenamiento de datos. Se usa COMMON para datos compartidos
y EQUIVALENCE cuando almacenamos una variable con dos posibles
tipos en la misma posición de memoria (como union en C). Se usa
DATA para inicializar datos estáticos.


CHARACTER S*10, T*25
DATA X/1.0/,Y/3.1416/,K/20/
Tipos definidos por el usuario, con TYPE <nombre>... END TYPE
<nombre>
46
FORTRAN. Control de secuencia
EL conjunto de estructuras de control es limitado:
 Expresiones, prioridad de operadores
 Enunciados
 Asignación,
cuando se hace entre cadenas hay ajuste
de tamaño con blancos o truncamiento.
 Condicional. Permite IF <cond> ELSE IF... Para
selección múltiple SELECT CASE <expr>
CASE.....CASE DEFAULT.... END SELECT
 Iteración. DO....END DO
 Nulo, se usa solo para la etiqueta. CONTINUE.


Control de subprogramas. CALL invoca al
subprograma y RETURN devuelve un valor al
programa llamante.
Construcciones propensas a error: GOTO.
47
FORTRAN. Entrada y Salida

Tipos de archivos:
 Secuenciales
 De


acceso directo
Comandos: READ, WRITE, PRINT, OPEN ,
CLASE, INQUIRE (propiedades o estado del
archivo) REWIND y ENDFILE (para ubicar el
puntero del fichero).
Para el tratamiento de excepciones en las
sentencias READ/WRITE se puede introducir la
posición de la rutina de dicho tratamiento
(ERR=90).
48
FORTRAN. Subprogramas

Hay tres tipos de subprogramas:
 Function,
devuelven un solo valor de tipo numérico,
lógico o cadena de caracteres.
 Subroutine, devuelve valores a través de variables no
locales COMMON.
 Función de enunciado, permite calcular una sola
expresión aritmética o lógica.


FN(X,Y)=SIN(X)**2-COS(Y)**2
Gestión de almacenamiento.
 Las
variables son locales o globales (COMMON)
 Recursividad: RECURSIVE FUNCTION FACTORIAL(X)
 Parámetros de subprograma. Paso por referencia.
49
Abstracción y encapsulamiento
FORTRAN. Evaluación del lenguaje


La abstracción es posible mediante los
subprogramas y el uso de variables COMMON,
aunque su uso es propenso a errores.
FORTRAN sigue siendo utilizado en el ámbito
científico y es muy eficiente realizando cálculos.
 La
estructura del programa suele ser dificil de entender.
 En FORTRAN 90 se incluye la recursividad y la memoria
dinámica.
 Las etiquetas de las sentencias ya no son necesarias, ni
el GOTO, pues se ha transformado en un lenguaje
estructurado.
 El aspecto de los programas sigue siendo de
procesamiento por lotes
50
Programación Imperativa o
Procedural: C

Desarrollado por Ritchie y Thompson en el 72.
 Multiuso (inicialmente
 Sintaxis compacta

para sistemas)
Historia
 60
Thompson desarrolla en Bell Multics, se crea un
lenguaje llamado B.
 70, el proyecto UNIX avanza y el lenguaje B se
queda pequeño, se comienza a desarrollar C
 82, C es distribuido con Unix y muy usado en las
universidades. ANSI comienza a desarrollar un
estándar
51
Perspectiva del lenguaje C

La programación en C se compone de:
 El
lenguaje C, con un limitado nº de estructuras
de control. No hay primitivas si no se usan las
librerías.
 El preprocesador de C (#), estos enunciados no
forman parte del lenguaje C y son
preprocesados antes de la compilación.
 Los supuestos de interfaz C (.h), lor archivos
“header” informan al usuario de las funciones
incluidad en una biblioteca.
 Las bibliotecas de C. Archivos obj o lib
conteniendo la implementación de las funciones.
52
Ejemplo anotado
53
Objetos de datos

Tipos de datos primitivos
 Los
nombres de variables no pueden comenzar con
dígito. Sensible a may-min.
 Los datos son enteros (char, short, long),
enumerados (enum) o float. Los punteros se declaran
con el tipo seguido de ‘*’.
 No hay booleanos.

Tipos de datos estructurados
 Arrays, comienzan en 0 y se guardan por filas.
 Tipos definidos por el usuario. Struct { }.
 Union, es una definición de tipo si tácticamente
con
un struct, pero todos los componentes ocupan la
misma memoria.
54
Representación de almacenamiento
Los tipos de C emplean básicamente la
representación hardware de sus datos.
 Una variable de tipo array es también el
puntero al primer elemento del array que
comienza con el índice 0.
 Es posible inicializar cualquier variable
declarada estáticamente.

55
Control de secuencia

Expresiones.Se emplea notación infija.

Coerciones, pueden ser forzadas haciendo una cast unaria
antes de un valor.


Enunciados. Pueden ser bloques de sentencias entre
llaves.






A + (int)b
Condicional, if...then...else...;
Condicinal múltiple, switch...{case....case...default...;}
Iterativos: while, do , for.
Transferencia del control: brak, continue, goto, return.
De preprocesador: #define, #include, #ifdef, #if...#undef...#else
C no tiene enunciados E/S, están en stdio.h.
56
Subprogramas y Gestión de
almacenamiento




main() es la función de entrada al programa
principal.
Cada función tiene asociado un registro de
activación, que la invoca cuando es llamada.
No hay anidamiento de funciones, por lo que las
variables son globales o locales. Las globales
deben ser declaradas por extern, para que sea
vistas por otros módulos. extern int i, j, k;
Las funciones de C sólo toman argumentos por
valor. Para simular paso por referencia hay que
pasar el puntero “por valor”.
57
Abstracción y encapsulamiento
El lenguaje da facilidades para la
definición de tipos, pero no implementa el
ocultamiento de la información, de manera
que si se tiene acceso a un struct, tambien
se accederá a todos sus componentes.
 El uso de bibliotecas con interfaces
header también permite la abstracción.

58
Evaluación del lenguaje

C es muy potente y popular:
 Flexible
 Eficiente
 Disponible
(se distribuye con Unix)
 Portatil

Pero C también permite una programación
descuidada y propensa a errores.
59
Lenguajes funcionales: LISP
60. McCarthy en el MIT
 Muy usado en IA
 En LISP la recursión se emplea a menudo
como estructura de control, lo que resta
eficiencia a las ejecuciones.
 La últimas versiones de LISP incluyen un
recolector de basura

60
Hola Mundo en LISP
61
Perspectiva del lenguaje


Interactivo (usualmente)
Los datos en LISP son muy restringidos:






Átomos literales (símbolos)
Átomos numéricos
La estructura de datos básica es la lista. Incluye
primitivas para su manipulación.
Los comentarios comienzan por ‘;’
Los parámetros de función van todos por valor o por
referencia según la clasificación de la función.
LISP es interpretado y usa una estructura de gestión de
almacenamiento en montículo con recolección de
basura como almacenamiento primario para datos y
programas.
62
Ejemplo anotado
63
Objetos de datos

Tipos de datos primitivos: átomos. Cada átomo
tiene una lista de propiedades asociada, accesible
a través del puntero que almacena el nombre del
átomo.
No se distinguen may-min para identificadores

Tipos de datos estructurado: listas. Tienen
asociado un puntero al primer elemento (car) y otro
al elemento siguiente (cdr). Una lista vacía apunta
a nil.
Para la asignación se utiliza setq(x val).
 Representación y almacenamiento.


Cada descriptor de un objeto de datos proporciona tipo y atributos.
En los datos estructurados (listas) se tienen sólo punteros a primero
y a siguiente.
64
Control de secuencia



El traductor LISP es una función read() que
toma el fuente del fichero y lo interpreta.
La ejecución del programa consiste en la
evaluación de las funciones contenidas en el
mismo.
Expresiones:
 Condicional
 Operaciones
 Operaciones
sobre átomos (en preorden): +, -, *, /
sobre listas: cons, car, cdr, list, replace,
null, equal.
 Operaciones sobre propiedades: put, get.
 Enunciados: prog() para ejecución secuencial.
 Entrada y salida: open(), read(), print().
 Definición de funciones: defun, define.
65
Gestión de subprogramas

Tres clases de funciones:
 Función
interpretada, en forma de estructura
de listas. Primitivas eval y apply.
 Función compilada, compiladas en un bloque
de código máquina que puede ser ejecutado
por el interprete del hardware.
 Macro, se declara con define. Es
simplemente una función ordinaria en LISP.
Puede ser interpretada y compilada.
66
Gestión de almacenamiento


La memoria se estructura en forma de montículo, que
maneja unidades de una palabra de tamaño fijo usando
una lista de espacios libres y un recolector de basura.
Entorno de referencia:



Local, es el que se da en las listas, como asociaciones de átomos
relacionados de una determinada manera.
Global o común, se consigue mediante asociación de un átomo
con una propiedad del mismo que contiene un puntero al datos
referenciado. Se usa set y setq.
Paso de parámetros:


Transmisión por valor, consiste en evaluar las expresiones de una
lista de parámetros y transmitir los valores resultantes.
Transmisión por nombre, transmitir las expresiones de la lista de
parámetros sin evaluar, y dejar que la función llamada los evalue
usando eval. En funciones macro la transmisión por nombre es la
norma. Para funciones lambda se puede especificar la transmisión
por nombre usando nlambda, en lugar de lambda.
67
Funciones en LISP I


Funciones normales, son las que se suelen incluir en las
implementaciones de LISP (ver manual en cada caso).
Funciones de lista, para manipulación de listas:






car L, devuelve el primer elemento de L.
cdr L, devuelve la cola (lista - primero).
cons x y, devuelve uan lista formada por x e y.
list x y z, devuelve la lista (x y z).
quote x, no se evalúa x
Predicados









atom x, devuelve True si x es un átomo.
numberp x, devuelve True si x es un número
greaterp x y, devuelve True si x>y
lessp x y, devuelve True si x<y
null x, devuelve True si x es nulo
and x y, devuelve x and y
or x y, devuelve x or y
not x, devuelve not x
eq x y, devuelve True si x=y
68
Funciones en LISP I

Funciones aritméticas:
 +,
-, *, y /.
 rem x y, devuelve el módulo x/y (remainder).

Funciones de entrada y salida
 load
nombrearchivo, lee el archivo a memoria
 print x, imprime el elemento x
 open nombrearchivo, abre un archivo y devuelve
una puntero al mismo
 read, lee del terminal un átomo
 help, proporciona ayuda
 trace, traza la función
 bye, termina LISP
69
Abstracción y encapsulamiento


LISP, en origen, no incluye características de
abstracción de datos.
CLOS fue una ampliación de LISP con
orientación de objetos. Características:
 Herencia
múltiple
 Funciones genéricas
 Metaclases y metaobjetos
 Técnica de creación e inicialización de objetos que
permite control del proceso por parte del usuario.
70
Evaluación del lenguaje
LISP ha evolucionado durante más de 30
años y desarrollado para inteligencia
artificial, pero no es adecuado para
aplicaciones convencionales.
 Las versiones compiladas son algo más
eficientes.

71
Programación lógica: PROLOG

PROLOG está orientado a la resolución de
problemas mediante el cálculo de predicados,
basado en:
 Preguntas
a la base de datos
 Pruebas matemáticas

El programa PROLOG especifíca cómo debe
ser la solución, en vez de dar el algoritmo para
su resolución. La solución se obtiene mediante
búsqueda aplicando la lógica de predicados.
72
Historia
Coulmerauer (1970) desarrolló un
lenguaje para hacer deducciones de texto
 Se aplica un mecanismo de resolución
sobre predicados especiales, cláusulas de
Horn, llamado unificación.
 La difusión del lenguaje se produce en los
80, pero de forma muy limitada debido a la
falta de aplicaciones en dicho lenguaje.

73
Hola mundo, en PROLOG
74
Perspectiva del lenguaje




El programa prolog se compone de unos hechos
(datos) y un conjunto de reglas, es decir, relaciones
entre objetos de la base de datos.
La ejecución del programa cargado en memoria
consiste en realizar una pregunta de forma
interactiva: el interprete generará por inferencia los
resultados que se deducen a partir del contenido de
la base de datos.
PROLOG tiene una sintaxis y semántica simples.
Sólo busca relaciones entre los objetos creados, las
variables y las listas, que son sus estructuras
básicas.
Comentarios entre /* */
75
Ejemplo anotado
76
Objetos de datos

Tipos de datos primitivos: variables y constantes:
 Enteros
 Reales
 Caracteres
Los identificadores con minúscula representan hechos,
los que van con mayúscula variables.
El alcance de una variable es la regla donde aparece.

Tipos de datos estructurados:
 Átomos:
constantes y variables de cadena
 Listas, representadas entre [ ]

Tipos definidos por el usuario. Las reglas para
definir relaciones pueden actuar como tipos de
77
usuario.
Representación de almacenamiento
Las reglas y hechos son almacenadas en
memoria como listas enlazadas.
 La ejecución de prolog consiste en una
búsqueda en profundidad de un árbol
conteniendo todas las posibles soluciones.
Para cada una de ellas se evaluará su
corrección. La búsqueda se puede hacer
más eficiente mediante la poda del árbol
de búsqueda (corte).

78
Control de secuencia
El orden de evaluación es secuencial
 Expresiones, operaciones aritméticas y operadores
relacionales. Not().
 Enunciados





Hechos, relaciones que se expresan en una consulta. Son
tuplas con un nombre de predicado y unos argumentos.
Reglas, implicaiones que se expresan en una operación consult
Preguntas, sucesión de términos que finalizan con un punto.
Cortes, (!), fuerza el retroceso en la búsqueda. Esto puede
impedir que se encuentren ciertas soluciones, pero puede hacer
más eficiente la búsqueda.
Entrada y salida, nl y write.
79
Subprogramas y gestión de almacenamiento

PROLOG tiene dos modos:

Modo consulta, se introducen nuevas relaciones (hechos) en el almacenamiento
dinámico de la base de datos.
 Modos pregunta, se ejecuta un intérprete basado en pilas para evaluar las preguntas
del usuario.

Alcance de las variables:

Ambiente local de referencia, todas las variables son locales a la regla en que están
definidas. La unificación hace interaccionar nombres locales de una regla con los de
otras reglas.
 Ambiente común de referencia, todos los datos son compartidos.
 Paso de parámetros, la unificación proporciona el paso de parámetros entre reglas.

Funciones normales, van integradas en el lenguaje:











Consult(nommbrearchivo)
Fail, siempre fracasa
See(nombrearchivo), lee las entradas de un archivo y las incorpora al conjunto de
reglas.
Write(término)
Tell(término), reorienta la salida del write al archivo
Told, cierra el archivo anterior
Nl, salto de línea
Atom(X), devuleve cierto si X es un átomo
Var(X), devuelve cierto si X es una variable
Integer(X), devuelve cierto si X es un entero
80
Trace, activa la depuración del programa
Abstracción y encapsulamiento

PROLOG no proporciona estas
capacidades.
81
Evaluación del lenguaje


PROLOG va bien para problemas de relaciones,
p.e. Tratamiento del lenguaje natural, y consulta
de bases de datos.
A pesar de que es posible desarrollar programas
sin especificar el algoritmo de resolución a
veces hay que echar mano de otro tipo de
programación para hacer los programas más
eficientes, y a menudo se emplea el corte para
limitar el espacio de búsqueda.
82
PROG. ORIENTADA A OBJETO
83
HERENCIA




Con frecuencia la información se pasa entre
componentes de programa de manera implícita,
a este traspaso de información le llamamos
herencia.
La herencia consiste en la recepción en un
componente de programa de propiedades o
características de otro componente de acuerdo
con la relación especial que existe entre ambos
componentes.
Las reglas de alcance de variables son una
forma de herencia.
La herencia múltiple se da cuando una clase
tienen varias superclases de las que hereda.
84
Clases derivadas


La herencia se implementa en los lenguajes orientados
a objetos a través de clases derivadas, que heredan
propiedades y métodos de sus superclases.
La visibilidad de los objetos heredados depende de la
forma en que se declaran:




PRIVATE
PUBLIC
PROTECTED
Implementación: En la clase derivada los nombre
derivados de la superclase se agregan al espacio.


Si en la definición hay una función constructora, hay que incluir
en la declaración una llamada a dicha función.
El objeto guarda la referencia de los apuntadores a todas las
propiedades y métodos, a esto se llama enfoque con base en
copia de la herencia (usado en C++).
85
Métodos


La herencia de métodos para crear objetos
nuevos proporciona un poder adicional que va
más allá del simple encapsulamiento.
En las clases derivadas, cuando se quiere
cambiar uno de los métodos hay dos
posibilidades:
 Redefinir el método en la clase derivada
 Usar una función virtual, que se enlaza
dinámicamente en el momento de llamada del
subprograma.
86
Clases abstractas


Se usa cuando la superclase define una especie de
plantilla para las subclases, aunque no permite que se
declaren objetos en esta definición. Esto requiere que
todos los objetos que requieren esta clase se definan de
una subclase derivada.
No se puede crear ningún objeto que tenga funciones
virtuales nulas, del tipo:


Virtual void NombreDeTipo()=0;
HERENCIA MIXIN. También se llama herencia de
incorporación, en la que solo se define la diferencia entre
la clase base y la clase derivada. Las diferencia se define
en una clase delta:
Deltaclass ModPila {}
 Class PilaNueva = class PilaElem + deltaclass ModPila
La ventaja es que las clase delta se pueden adicionar a cualquier
clase.

87
Objetos y mensajes

El lenguaje Smalltalk presenta 3 características:
 Definición
de clase. Define la estructura interna y los
métodos que se pueden usar para crear y manipular
objetos.
 Ejemplarización de objetos. Se crean objetos
específicos para cada definición de clase.
 Paso de mensajes. Los métodos se pasan como
mensajes a un objeto para llevar a cabo una acción.
Tipos:



Un mensaje unario es un método sin parámetros.
El mensaje binario se usa, principalmente, para operadores
aritméticos.
Los mensajes de palabra clave se usan para hacer
asignaciones de valor, por ejemplo, en un array:


X_Array new: 10
X at:3 put:42
88
Herencia de clases
Si se envía un mensaje a un objeto con un
método que no está definido en su clase
se pasa a la clase progenitora, y así
sucesivamente.
 En los métodos de palabra clave el
parámetro se nombra de forma explícita
en la declaración del método

89
Conceptos de abstracción


El encapsulamiento es un mecanismo divide y vencerás
para proporcionar control sobre el programa en
desarrollo.
La abstracción y la herencia puede ser usada para
impedir al programador ver el contenido de los objetos
de datos que no convenga. La herencia,
fundamentalmente, es un mecanismo para pasar
información entre objetos en clases relacionadas.
Permite:




Especialización, para que los objetos derivados contengan
caracterísiticas de otros objetos.
Descomposición, permite separar una abstracción en sus
componentes. Lo contrario es la agregación.
Ejemplarización, es el proceso de crear ocurrencias de una
clase (se trata de un proceso de copia).
Individualización, objetos similares se agrupan con otros para
propósitos comunes. Es lo contrario de agrupamiento.
90
POLIMORFISMO

El polimorfismo es la capacidad de un solo
operador o nombre de subprograma para
referirse a varias definiciones en función
del contexto, es decir, de los tipos de daos
de los argumentos y del resultado.
91