You are on page 1of 64

FACULTAD DE INGENIERÍA

E.A.P. INGENIERÍA DE SISTEMAS E INFORMÁTICA

MANUAL DEL CURSO:

Teoría de Lenguajes
(Unidad I)

Tema:
Introducción a la teoría de Lenguajes

Dictado por:
DIANA CECILIA MUÑOZ CASANOVA
M.S. en Ingeniería de Sistemas e Informática

CHIMBOTE – PERÚ
2007
CAPÍTULO I: HISTORIA DE LOS LENGUAJES DE PROGRAMACIÓN

1.1. Introducción 2
1.2. Historia de los lenguajes de programación 3
1.3. Tendencias en los lenguajes de programación 7

CAPÍTULO II: EVOLUCIÓN DE LOS LENGUAJES DE PROGRAMACIÓN

2.1. Evolución de los lenguajes de programación 11


2.1.1.Estructurados vs. No estructurados 11
2.1.2.1985-1990 y el nacimiento del xbase 11
2.1.3.Los primeros años, 1990-1995: las bases de datos relacionales 12
2.1.4.La segunda mitad, 1995-2000: la orientación a objetos 12
2.1.5.El fin de los lenguajes D.O.S. 13
2.1.6.2000 y más allá: lenguajes visuales 13
2.1.7.Una visión a la web y al futuro: html, perl, php, pithon, java y otros 14
2.2. Generaciones de lenguajes de programación 15
2.3. Tipos de lenguaje de programación según su campo de aplicación. 15
2.4. Tipos de lenguaje de programación en función al estilo de programar 16
2.5. Lenguajes imperativos 16
2.6. Lenguajes funcionales 18
2.6.1.Concepto matemático de función. 18
2.6.2.Concepto de lenguajes funcionales. 19
2.6.3.Categorías de lenguajes funcionales. 20
2.6.4.Problemas del modelo imperativo 20
2.7. Lenguajes lógicos (declarativos) 22
2.8. Lenguajes orientados a objetos 26
2.9. Lenguajes con concurrencia 27
2.10.Evolución de los lenguajes de programación declarativos 29
2.11.Evolución de los lenguajes de programación orientado a objetos e
Imperativos 30

CAPÍTULO III: CONCEPTOS EN LOS LENGUAJES DE PROGRAMACIÓN

3.1. ¿Qué es lo que constituye un buen lenguaje? 31


3.1.1.Atributos de un buen lenguaje 31
3.1.2.Estandarización de los lenguajes 32
3.2. Sintaxis de lenguajes de programación 32
3.3. Tipos de datos 33
3.4. Abstracción 34
3.5. Abstracción en programación 34
3.6. Clases de abstracción 35
3.6.1.Abstracción de control 35
3.6.2.Abstracción de datos. 37
3.7. Tipos abstractos de datos (TADS) 37
3.8. Lenguajes de programación y TADS 37
3.9. Lenguajes de programación que deberías aprender 39
3.9.1.PHP 39
3.9.2.C# 39
3.9.3.AJAX 40
3.9.4.Javascript 40
3.9.5.PERL 41
3.9.6.C41
3.9.7.Ruby y ruby on rails 41
3.9.8.ASP 42

CAPÍTULO IV: LENGUAJES DE BAJO, MEDIO Y ALTO NIVEL

4.1. Introducción 43
4.2. Lenguajes de bajo nivel 43
4.2.1.Lenguaje máquina. 44
4.2.2.Ensamblador. 44
A) Ventajas del lenguaje ensamblador 45
B) Desventajas del lenguaje ensamblador 48
4.3. Lenguajes de medio nivel 49
4.4. Lenguajes De Alto Nivel 52
4.5. Generadores de aplicaciones o 4º nivel 53

CAPÍTULO V: ELEMENTOS DE UN LENGUAJE DE PROGRAMACIÓN

5.1. Elementos sintácticos de un lenguaje 54


5.2. Tipos de datos 55
5.3. Notaciones de expresiones 56
5.4. Propiedad asociativa y precedencia 56
5.5. Representación de árbol para expresiones 57
5.6. Evaluación de expresiones 57
5.6.1.Evaluación mediante la reconstrucción de un árbol 57
5.6.2.Evaluación mediante una pila 58
A) Algoritmo para transformar una notación infija a postfija 58
B) Tabla de prioridades. 60
C) Algoritmo (pseudocódigo) 60
CAPÍTULO I: HISTORIA DE LOS LENGUAJES DE
PROGRAMACIÓN

1.1. INTRODUCCIÓN

Una computadora es una máquina que solo comprende las instrucciones que se le
den en un determinado formato. Cada máquina reconoce y ejecuta un número de
instrucciones diferentes que se agrupan en los distintos lenguajes de
programación.
Un lenguaje de programación es un conjunto limitado de palabras y de símbolos
que representan procedimientos, cálculos, decisiones y otras operaciones que
pueden ejecutar una computadora. A pesar de que en este trabajo parte de la
división de lenguajes de programación en imperativos y declarativos (los cuales a
su vez se dividen en numerosos subgrupos), la clasificación más común y básica
que suele hacerse de los lenguajes de programación es la que los divide en
lenguajes de bajo y de alto nivel. Los lenguajes de programación de bajo nivel
fueron los primeros que surgieron y se llaman así porque están directamente
relacionados con el hardware del computador, es decir, el usuario introduce una
serie de códigos numéricos que la máquina va a interpretar como instrucciones.
Para usar este lenguaje, el programador tenía que conocer el funcionamiento de la
máquina al más bajo nivel y los errores de programación eran muy frecuentes.
Los lenguajes de alto nivel surgieron con posterioridad con el primer compilador
de FORTRAN (FORmula TRANslation), que, como su nombre indica, inició
como un "simple" esfuerzo de traducir un lenguaje de fórmulas, al lenguaje
ensamblador y por consiguiente al lenguaje de máquina, facilitando la labor a los
programadores. A partir de FORTRAN, se han desarrollado innumerables
lenguajes, que siguen el mismo concepto: facilitar la vida al programador,
aumentando la productividad. Estos lenguajes usan un número reducido de
instrucciones (normalmente en inglés) que siguen unas estrictas reglas
gramaticales que se conocen como sintaxis del lenguaje. Pero aunque el
programador de esta forma se distancie del hardware del computador, este sigue
trabajando en lenguaje máquina. Por ello se hace necesaria una traducción a una
secuencia de instrucciones interpretables por el computador. Esta labor es llevada
a cabo por los compiladores y los intérpretes.
El compilador es un programa que se encarga de la traducción global del programa
realizado por el usuario. Esta operación recibe el nombre de compilación. El
programa es traducido completamente antes de que se ejecute, por lo que la
ejecución se realiza en un periodo muy breve. El intérprete por el contrario lleva a
cabo una traducción inmediata en el momento de la ejecución, es decir, irá
ejecutando las instrucciones una a una haciendo que el proceso requiera un
periodo de tiempo sensiblemente mayor del que necesitaría un compilador. Los
intérpretes son usados para traducir programas de alta dificultad de
implementación, en estos casos, las órdenes a traducir son de tal complejidad que
no merece la pena crear un compilador ya que este también tendría que ser de una
complejidad por encima de lo normal.
Hay que mencionar la existencia de lenguajes que combinan características de los
de alto nivel y los de bajo nivel (es decir, Ensamblador). Un ejemplo es C:
contiene estructuras de programación de alto nivel; sin embargo, fue diseñado con
muy pocas instrucciones, las cuales son sumamente sencillas, fáciles de traducir al
lenguaje de la máquina; y requiere de un entendimiento apropiado de cómo
funciona la máquina, el uso de la memoria, etcétera. Por ello, algunos consideran a
lenguajes como C (que fue diseñado para hacer sistemas operativos), lenguajes de
nivel medio, si bien, son considerados mayoritariamente de bajo nivel.

1.2. HISTORIA DE LOS LENGUAJES DE PROGRAMACIÓN

Los primeros lenguajes de programación surgieron de la idea de Charles Babagge,


la cual se le ocurrió a este hombre a mediados del siglo XIX. Era un profesor
matemático de la universidad de Cambridge e inventor ingles, que la principio del
siglo XIX predijo muchas de las teorías en que se basan los actuales ordenadores.
Consistía en lo que él denominaba la maquina analítica, pero que por motivos
técnicos no pudo construirse hasta mediados del siglo XX. Con él colaboro Ada
Lovedby, la cual es considerada como la primera programadora de la historia, pues
realizo programas para aquélla supuesta maquina de Babagge, en tarjetas
perforadas. Como la maquina no llego nunca a construirse, los programas de Ada,
lógicamente, tampoco llegaron a ejecutarse, pero si suponen un punto de partida
de la programación, sobre todo si observamos que en cuanto se empezó a
programar, los programadores utilizaron las técnicas diseñadas por Charles
Babagge, y Ada, que consistían entre otras, en la programación mediante tarjetas
perforadas. A pesar de ello, Ada ha permanecido como la primera programadora
de la historia. Se dice por tanto que estos dos genios de antaño, se adelantaron un
siglo a su época, lo cual describe la inteligencia de la que se hallaban dotados.
En 1823 el gobierno Británico lo apoyo para crear el proyecto de una máquina de
diferencias, un dispositivo mecánico para efectuar sumas repetidas. Pero Babagge
se dedico al proyecto de la máquina analítica, abandonando la maquina de
diferencias, que se pudiera programar con tarjetas perforadas, gracias a la creación
de Charles Jacquard (francés). Este hombre era un fabricante de tejidos y había
creado un telar que podía reproducir automáticamente patrones de tejidos, leyendo
la información codificada en patrones de agujeros perforados en tarjetas de papel
rígido. Entonces Babagge intento crear la máquina que se pudiera programar con
tarjetas perforadas para efectuar cualquier cálculo con una precisión de 20 dígitos.
Pero la tecnología de la época no bastaba para hacer realidad sus ideas. Si bien las
ideas de Babagge no llegaron a materializarse de forma definitiva, su contribución
es decisiva, ya que los ordenadores actuales responden a un esquema análogo al de
la máquina analítica. En su diseño, la máquina constaba de cinco unidades básicas:
1) Unidad de entrada, para introducir datos e instrucciones.
2) Memoria, donde se almacenaban datos y resultados intermedios.
3) Unidad de control, para regular la secuencia de ejecución de las operaciones.
4) Unidad Aritmético-Lógica, que efectúa las operaciones.
5) Unidad de salida, encargada de comunicar al exterior los resultados.

Charles Babbage, conocido como el "padre de la informática" no pudo completar


en aquella época la construcción del computador que había soñado, dado que
faltaba algo fundamental: la electrónica. El camino señalado de Babbage, no fue
nunca abandonado y siguiéndolo, se construyeron las primeras computadoras.
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.
John Von Neumann desarrolló el modelo que lleva su nombre, para describir este
concepto de "programa almacenado". En este modelo, se tiene una abstracción de
la memoria como un conjunto de celdas, que almacenan simplemente números.
Estos números pueden representar dos cosas: los datos, sobre los que va a trabajar
el programa; o bien, el programa en sí.
¿Cómo es que describimos un programa como números? Se tenía el problema de
representar las acciones que iba a realizar la computadora, y que la memoria, al
estar compuesta por switches correspondientes al concepto de bit, solamente nos
permitía almacenar números binarios.
La solución que se tomó fue la siguiente: a cada acción que sea capaz de realizar
nuestra computadora, asociarle un número, que será su código de operación
(opcode). Por ejemplo, una calculadora programable simple podría asignar los
opcodes:
1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE.
Supongamos que queremos realizar la operación 5 * 3 + 2, en la calculadora
descrita arriba. En memoria, podríamos "escribir" el programa de la siguiente
forma: Localidad Opcode Significado Comentario 0 5 5 En esta localidad,
tenemos el primer número de la fórmula 1 3 * En esta localidad, tenemos el
opcode que representa la multiplicación. 2 3 3 En esta localidad, tenemos el
segundo número de la fórmula 3 1 + En esta localidad, tenemos el opcode que
representa la suma. 4 2 2 En esta localidad, tenemos el último número de la
fórmula. Podemos ver que con esta representación, es simple expresar las
operaciones de las que es capaz el hardware (en este caso, nuestra calculadora
imaginaria), en la memoria.
La descripción y uso de los opcodes es lo que llamamos lenguaje de máquina. Es
decir, la lista de códigos que la máquina va a interpretar como instrucciones,
describe las capacidades de programación que tenemos de ella; es el lenguaje más
primitivo, depende directamente del hardware, y requiere del programador que
conozca el funcionamiento de la máquina al más bajo nivel.
Los lenguajes más primitivos fueron los lenguajes de máquina. Esto, ya que el
hardware se desarrolló antes del software, y además cualquier software finalmente
tiene que expresarse en el lenguaje que maneja el hardware.
La programación en esos momentos era sumamente tediosa, pues el programador
tenía que "bajarse" al nivel de la máquina y decirle, paso a pasito, cada punto de la
tarea que tenía que realizar. Además, debía expresarlo en forma numérica; y por
supuesto, este proceso era propenso a errores, con lo que la productividad del
programador era muy limitada. Sin embargo, hay que recordar que en estos
momentos, simplemente aún no existía alternativa.
El primer gran avance que se dio, fue la abstracción dada por el Lenguaje
Ensamblador, y con él, el nacimiento de las primeras herramientas automáticas
para generar el código máquina. Esto redujo los errores triviales, como podía ser
el número que correspondía a una operación, que son sumamente engorrosos y
difíciles de detectar, pero fáciles de cometer. Sin embargo, aún aquí es fácil para el
programador perderse y cometer errores de lógica, pues debe bajar al nivel de la
forma en que trabaja el CPU, y entender bien todo lo que sucede dentro de él.
Con el desarrollo en los 50s y 60s de algoritmos de más elevado nivel, y el
aumento de poder del hardware, empezaron a entrar al uso de computadoras
científicos de otras ramas; ellos conocían mucho de Física, Química y otras ramas
similares, pero no de Computación, y por supuesto, les era sumamente complicado
trabajar con lenguaje Ensamblador en vez de fórmulas. Así, nació el concepto de
Lenguaje de Alto Nivel, con el primer compilador de FORTRAN (FORmula
TRANslation), que, como su nombre indica, inició como un "simple" esfuerzo de
traducir un lenguaje de fórmulas, al lenguaje ensamblador y por consiguiente al
lenguaje de máquina. A partir de FORTRAN, se han desarrollado innumerables
lenguajes, que siguen el mismo concepto: buscar la mayor abstracción posible, y
facilitar la vida al programador, aumentando la productividad, encargándose los
compiladores o intérpretes de traducir el lenguaje de alto nivel, al lenguaje de
computadora.
Hay que notar la existencia de lenguajes que combinan características de los de
alto nivel y los de bajo nivel (es decir, Ensamblador). El ejemplo mas apropiado
podría ser el lenguaje C ya que puede acceder a los registros del sistema, trabajar
con direcciones de memoria, todas ellas características de lenguajes de bajo nivel
y a la vez realizar operaciones de alto nivel.
1.3. TENDENCIAS EN LOS LENGUAJES DE PROGRAMACIÓN

El estudio de los lenguajes de programación agrupa tres intereses diferentes; el del


programador profesional, el del diseñador del lenguaje y del Implementador del
lenguaje.
Además, estos tres trabajos han de realizarse dentro de las ligaduras y capacidades
de la organización de una computadora y de las limitaciones fundamentales de la
propia "calculabilidad".
 El termino "el programador" es un tanto amorfo, en el sentido de que camufla
importantes diferencias entre distintos niveles y aplicaciones de la
programación. Claramente el programador que ha realizado un curso de doce
semanas en COBOL y luego entra en el campo del procesamiento de datos es
diferente del programador que escribe un compilador en Pascal, o del
programador que diseña un experimento de inteligencia artificial en LISP, o
del programador que combina sus rutinas de FORTRAN para resolver un
problema de ingeniería complejo, o del programador que desarrolla un sistema
operativo multiprocesador en ADA.
 El "diseñador del lenguaje" es también un termino algo nebuloso. Algunos
lenguajes (como APL y LISP) fueron diseñados por una sola persona con un
concepto único, mientras que otros (FORTRAN y COBOL) son el producto de
desarrollo de varios años realizados por comités de diseño de lenguajes.
 El "Implementador del lenguaje" es la persona o grupo que desarrolla un
compilador o interprete para un lenguaje sobre una maquina particular o tipos
de maquinas. Mas frecuentemente, el primer compilador para el lenguaje Y
sobre la maquina X es desarrollada por la corporación que manufactura la
maquina X. Por ejemplo, hay varios compiladores de Fortran en uso; uno
desarrollado por IBM para una maquina IBM, otro desarrollado por DEC para
una maquina DEC, otro por CDC, y así sucesivamente. Las compañías de
software también desarrollan compiladores y también lo hacen los grupos de
investigación de las universidades

Hay también muchos aspectos compartidos entre los programadores, diseñadores


de un lenguaje implementadores del mismo. Cada uno debe comprender las
necesidades y ligaduras que gobiernan las actividades de los otros dos.
Hay, al menos, dos formas fundamentales desde las que pueden verse o
clasificarse los lenguajes de programación: por su nivel y por principales
aplicaciones. Además, estas visiones están condicionadas por la visión histórica
por la que ha transcurrido el lenguaje
Los "Lenguajes Declarativos" son los más parecidos al castellano o ingles en su potencia
expresiva y funcionalidad están en el nivel mas alto respecto a los otros. Son
fundamentalmente lenguajes de ordenes, dominados por sentencias que expresan "Lo que
hay que hacer" en ves de "Como hacerlo".
Los lenguajes de " Alto Nivel" son los mas utilizados como lenguaje de programación.
Aunque no son fundamentalmente declarativos, estos lenguajes permiten que los
algoritmos se expresen en un nivel y estilo de escritura fácilmente legible y comprensible
por otros programadores.
Los "Lenguajes Ensambladores" y los "Lenguajes Maquina" son dependientes de la
maquina. Cada tipo de maquina, tal como VAX de digital, tiene su propio lenguaje
maquina distinto y su lenguaje ensamblador asociado. El lenguaje Ensamblador es
simplemente una representación simbólica del lenguaje maquina asociado, lo cual permite
una programación menos tediosa que con el anterior.
La programación de un lenguaje de alto nivel o en un lenguaje ensamblador requiere, por
tanto, algún tipo de interfaz con el lenguaje maquina para que el programa pueda
ejecutarse. Las tres interfaces mas comunes: un "ensamblador" , un "compilador" y un
"interprete". El ensamblador y el compilador traduce el programa a otro equivalente en el
lenguaje X de la maquina "residente" como un paso separado antes de la ejecución. Por
otra parte, el interprete ejecuta directamente las instrucciones en un lenguaje Y de alto
nivel, sin un paso de procesamiento previo.
Algunos lenguajes son lenguajes principalmente interpretados, como APL, PROLOG y
LISP. El resto de los lenguajes -- Pascal, FORTRAN, COBOL, PL/I, SNOBOL, C, Ada y
Modula-2 – son normalmente lenguajes compilados. En algunos casos, un compilador
estará utilizable alternativamente para un lenguaje interpretado (tal como LISP) e
inversamente (tal como el interprete SNOBOL4 de los laboratorios Bell). Frecuentemente
la interpretación es preferible a la compilación en un entorno de programación
experimental o de educación, donde cada nueva ejecución de un programa implicado un
cambio en el propio texto del programa. La calidad de diagnosis y depuración que
soportan los lenguajes interpretados es generalmente mejor que la de los lenguajes
compilados, puesto que los mensajes de error se refieren directamente a sentencias del
texto del programa original. Además, la ventaja de la eficiencia que se adjudica
tradicionalmente a los lenguajes compilados frente a los interpretados puede pronto ser
eliminado, debido a la evolución de las maquinas cuyos lenguajes son ellos
mismos1lenguajes de alto nivel. Como ejemplo de estos están las nuevas maquinas LISP,
las cuales han sido diseñadas recientemente por Symbolics y Xerox Corporations.
Los lenguajes de Programación son tomados de diferentes perspectivas. Es importante
para un programador decidir cuales conceptos emitir o cuales incluir en la programación.
Con frecuencia el programador es osado a usar combinaciones de conceptos que hacen al
lenguaje "DURO" de usar, de entender e implementar. Cada programador tiene en mente
un estilo particular de programación, la decisión de incluir u omitir ciertos tipos de datos
que pueden tener una significativa influencia en la forma en que el Lenguaje es usado, la
decisión de usar u omitir conceptos de programación o modelos.
Existen cinco estilo de programación y son los siguientes:
1. Imperativa : Entrada, procesamiento y salidas de Datos.
2. Funcional : "Funciones", los datos son funciones, los resultados pueden ser un valor
o una función.
3. Lógico : {T,F} + operaciones lógicos (Inteligencia Artificial).
4. Orientados a Objetos: Clases, encapsulamiento de datos Herencia de datos,
polimorfismo
5. Concurrente.

El programador, diseñador e implementador de un lenguaje de programación deben


comprender la evolución histórica de los lenguajes para poder apreciar por que presentan
características diferentes. Por ejemplo, los lenguajes "mas jóvenes" desaconsejan (o
prohiben) el uso de las sentencias GOTO como mecanismo de control inferior, y esto es
correcto en el contexto de las filosofías actuales de ingeniería del software y
programación estructurada. Pero hubo un tiempo en que la GOTO, combinada con la IF,
era la única estructura de control disponible; el programador no dispone de algo como la
construcción WHILE o un IF-THEN-ELSE para elegir. Por tanto, cuando se ve un
lenguaje como FORTRAN, el cual tiene sus raíces en los comienzos de la historia de los
lenguajes de programación, uno no debe sorprenderse de ver la antigua sentencia GOTO
dentro de su repertorio.
Lo mas importante es que la historia nos permite ver la evolución de familias de
lenguajes de programación, ver la influencia que ejercer las arquitecturas y aplicaciones
de las computadoras sobre el diseño de lenguajes y evitar futuros defectos de diseño
aprendido las lecciones del pasado. Los que estudian se han elegido debido a su mayor
influencia y amplio uso entre los programadores, así como por sus distintas características
de diseño e implementacion. Colectivamente cubren los aspectos más importantes con los
que ha de enfrentarse el diseñado de lenguajes y la mayoría de las aplicaciones con las
que se enfrenta el programador.
También varios lenguajes están prefijados por las letras ANSI. Esto significa que el
American National Standards Institute ha adoptado esa versión del lenguaje como el
estándar nacional. Una vez que un lenguaje esta estandarizado, las maquinas que
implementan este lenguaje deben cumplir todas las especificaciones estándares,
reforzando así el máximo de transportabilidad de programas de una maquina a otra. La
policía federal de no comprar maquinas que no cumplan la versión estándar de cualquier
lenguaje que soporte tiende a "fortalecer" el proceso de estandarizacion, puesto que el
gobierno es, con mucho, el mayor comprador de computadoras de la nación.
Finalmente, la notación algebraica ordinaria, por ejemplo, influyo fuertemente en el
diseño de FORTRAN y ALGOL. Por otra parte, el ingles influyo en el desarrollo del
COBOL. El lambda calculo de Church dio los fundamentos de la notación funcional de
LISP, mientras que el algoritmo de Markov motivo el estilo de reconocimiento de formas
de SNOBOL. La arquitectura de computadoras de Von Neumann, la cual fue una
evolución de la maquina mas antigua de Turing, es el modelo básico de la mayoría de los
diseños de computadoras de las ultimas tres décadas. Esta maquina no solo influyeron en
los primeros lenguajes sino que también suministraron el esqueleto operacional sobre el
que evoluciono la mayoría de la programación de sistemas.
Una discusión mas directa de todos estos primeros modelos no están entre los objetivos de
este texto. Sin embargo, es importante apuntar aquí debido a su fundamental influencia en
la evolución de los primeros lenguajes de programación, por una parte, y por su estado en
el núcleo de la teoría de la computadora, por otra. Mas sobre este punto, cualquier
algoritmo que pueda describirse en ingles o castellano puede escribirse igualmente como
una maquina de Turing (maquina de Von Neumann), un algoritmo de Markov o una
función recursiva. Esta sección, conocida ampliamente como "tesis de Church", nos
permite escribir algoritmos en distintos estilos de programación (lenguajes) sin sacrificar
ninguna medida de generalidad, o potencia de programación, en la transición.
CAPÍTULO II: EVOLUCIÓN DE LOS LENGUAJES DE
PROGRAMACIÓN

2.1. EVOLUCIÓN DE LOS LENGUAJES DE PROGRAMACIÓN

2.1.1.ESTRUCTURADOS VS. NO ESTRUCTURADOS


A partir de C el gran lenguaje, y Pascal; se dividen los lenguajes en
estructurados (aquellos que en su codificación usaban una estructura jerárquica
de procedimientos y funciones), en contraposición a los lenguajes no
estructurados como el Basic cuya codificación se basaba en líneas de
programación, permitiendo al programador "saltar" de una línea de instrucción
a otra, haciendo que el código fuera algunas veces inentendible y muy difícil
de mantener (modificar) porque no seguía una estructura.
Basic de todos modos evolucionó, primero con el ahora primitivo GW Basic,
teniendo su máxima expresión con el Quick Basic del D.O.S. 5.0, el cual ya
incluía algunos conceptos mas de avanzada y más "aggiornados" a lo que eran
sus contrapartes estructuradas.

2.1.2.1985-1990 Y EL NACIMIENTO DEL XBASE


DBase fue el gran desarrollo para base de datos de los años 80. Bajo la batuta
de la firma Ashton Tate, empresa que dio origen a un interprete de bases de
datos muy sencillo y poderoso: dBbase II. Luego vinieron el dBase III+ que
hizo furor, y la etapa de la decadencia para dBase: el dBase IV, ya bajo la
dirección de Borland.
Así surgió el gran compilador Clipper, de Nantucket Corp., en su versión
Autumm 86 que permitía generar ejecutables libres de royalties y sin runtimes,
incluso tomando en forma directa el código dBase. Pero no solo era eso,
proveia cientos de comandos y funciones para potenciar al dBase.
Al ver el éxito de dBase y Clipper, surgió la empresa Fox Software que
desarrollo el FoxBase (un clon de dBase III+) y supero al "maestro" con su
versión Fox Plus, pero aun así, nunca pudo superar a Clipper ya que siempre
lidio con su política de necesitar de runtimes para su ejecución, cosa que
Clipper nunca necesitó.
2.1.3.LOS PRIMEROS AÑOS, 1990-1995: LAS BASES DE DATOS
RELACIONALES
A principios de la década pasada, se nota la evolución de los lenguajes de
programación. En forma profesional y aplicaciones de alto nivel, el lenguaje
preferido era C.
Para el aprendizaje se usaba Pascal, que permitía inculcar el concepto de
programación estructurada.
También Basic, era un lenguaje utilizado, no en pocas ocasiones en forma
profesional, aunque con ciertas limitaciones; su reinado estuvo en los años 80.
En lenguaje C, fue y todavía es el gran artífice de la computación actual. A
partir de el se desarrollaron compiladores que realmente constituían otros
lenguajes de programación. Es decir un lenguaje que crea otros lenguajes. Tal
es el caso de la estrella de la primera mitad de la década pasada: Clipper de
Nantucket Corp., el gran compilador de lenguaje Xbase. Clipper fue criticado
por los profesionales de la programación quienes aducían que no era un
lenguaje, sino un simple compilador nacido de la necesidad de aligerar la
ejecución de código del Interprete que le dio su origen, es decir el dBase. Pero
realmente Clipper, gracias a llevar dentro su código un corazón de lenguaje C,
fue muy fácil de utilizar y alcanzo gran popularidad.
Se desarrollaron librería externas, y con la programación al estilo C a partir de
su versión 5.0 y la inclusión de objetos, se convirtió en uno de los favoritos de
la programación administrativa, junto con Pascal.
Todos los lenguajes Xbase se basaban en el concepto de bases de datos
relacionales, es decir la agrupación de la información en forma de tablas,
denominadas campos y registros, cada uno de ellos preformateados para
recibir cierto tipo de dato (ej: fechas, caracteres, números, valores lógicos,
etc.); pudiendo "unir" diferentes bases por medio de campos comunes.

2.1.4.LA SEGUNDA MITAD, 1995-2000: LA ORIENTACIÓN A OBJETOS


A medida que los años van pasando el concepto de Bases relacionales empieza
a decaer relativamente, surge entonces una variante que se aplica a todos los
lenguajes: La orientación a objetos. Ya no solo se habla de programación
estructurada, sino que los módulos de programación son vistos como objetos,
las estructuras representan objetos y/o funciones que se adaptan en forma
general a procesos específicos es la maximización de la programación
modular.
El modelo de objetos engloba los conceptos de encapsulación, herencia y
poliformismo, el cual se aplica a los datos y al tipo de bases de datos que
almacena la información.
La orientación a objetos significa la agrupación de entidades de datos de forma
global, de tal manera que puedan ser interpretados de una forma común por
una misma estructura de programación.

2.1.5.EL FIN DE LOS LENGUAJES D.O.S.


Windows 95 marca el comienzo del fin de la programación D.O.S. y por lo
tanto de los lenguajes basados en este. Este proceso no fue enérgico, todavía
hoy, estamos viviendo esta etapa. Todavía hay numerosos y excelentes
sistemas desarrollados bajo entorno D.O.S. ejecutándose pero cada vez son los
menos.
Veamos que hicieron los lenguajes D.O.S. para mantenerse en el mercado:
Clipper trato de evolucionar hacia Windows bajo la batuta de Computer
Associates con el nombre de Visual Objects, el cual fue un fracaso. Al igual
que Visual Dbase 5.0 bajo la órbita de Borland.
Los únicos "sobrevivientes" al menos en esencia son Visual Fox (Microsoft),
Visual Basic (Microsoft), Delphi (Borland) y Visual C (Microsoft)

2.1.6.2000 Y MÁS ALLÁ: LENGUAJES VISUALES


Con al llegada de Windows todo es Visual, todo es iconos, todo es botones,
todo es Ventanas. Para programar en lenguajes visuales, primero hay que
comprender lo que es Windows. La forma de programar los sistemas
evolucionó radicalmente. Con Windows es preciso programar conservando las
convenciones del mismo, guardando sus características y funcionalidades. Los
sistemas hechos para Windows, deben ser tan Windows como el propio
sistema operativo.
La forma de programar se basa en objetos, cada uno de los cuales tiene sus
Propiedades y funciones. Se basa en la programación de eventos para dichos
objetos. Otro detalle es que la programación se basa en componentes (OLE,
OCX, ActiveX), los cuales reducen notablemente el trabajo de la
programación al proporcionar herramientas antes impensadas en la
programación D.O.S.
Todos los lenguajes visuales ofrecen RAD (Rapid Aplication Development) o
Wizzards; con lo cual comenzaron a prometer hacer aplicaciones en poco
tiempo, incluso para inexpertos. Lejos estaban ya los tiempos en que
programar era solo usar un simple editor de textos. Ahora las herramientas de
programación son poderosas. Son casi un sistema operativo, por asi decirlo;
con entornos de desarrollo avanzado y excelentes Debuggers. Las incursiones
cada vez mas innovadoras de Microsoft parecen imponer a la web como el
centro de desarrollo de aplicaciones: Microsoft .NET

2.1.7.UNA VISIÓN A LA WEB Y AL FUTURO: HTML, PERL, PHP, PITHON,


JAVA Y OTROS
Internet ha sido el disparador de nuevos lenguajes tales como el HTML que es
el lenguaje de programación de las páginas WEB para hipertexto. El mismo
constituye una codificación bastante simple, basada en marcadores (TAGs).
De la misma manera, cuando se hace necesario proveer de funciones
adicionales a un servicio web se recurre a Perl o a Pithon que son lenguajes
que nos permiten escribir scripts para ser alojados en los servidores a efectos
de proveer contadores, estadísticas, rankings, etc.
Por otra parte Java, bajo la dirección de SUN, constituye la idea de la
programación abierta y universal para las aplicaciones de escritorio, pero
todavía los estándares visuales (C, Basic y Delphi), son demasiado poderosos
como para desplazarlos, a pesar de que Java promete también ser un lenguaje
de excelentes prestaciones. Las nuevas tecnologías WEB inundan el mercado:
PHP, ASP, XML, DHTML, XHTML, AJAX lo cual enriquecen la forma de
manejar la información y su presentación al usuario final.
2.2. GENERACIONES DE LENGUAJES DE PROGRAMACIÓN

La evolución de los lenguajes de programación se puede dividir en 5 etapas o


generaciones.
1. Primera generación: lenguaje maquina.
2. Segunda generación: se crearon los primeros lenguajes ensambladores.
3. Tercera generación: se crean los primeros lenguajes de alto nivel. Ej. C,
Pascal, Cobol…
4. Cuarta generación. Son los lenguajes capaces de generar código por si solos,
son los llamados RAD, con lo cuales se pueden realizar aplicaciones sin ser un
experto en el lenguaje. Aquí también se encuentran los lenguajes orientados a
objetos, haciendo posible la reutilización d partes del código para otros
programas.
5. Quinta generación: aquí se encuentran los lenguajes orientados a la
inteligencia artificial.. Ej. PROLOG

2.3. TIPOS DE LENGUAJE DE PROGRAMACIÓN SEGÚN SU CAMPO DE


APLICACIÓN.

 Aplicaciones científicas.
En este tipo de aplicaciones predominan las operaciones numéricas o
matriciales propias de algoritmos matemáticos. Lenguajes adecuados son
FORTRAN y PASCAL

 Aplicaciones en procesamiento de datos.


En estas aplicaciones son frecuentes las operaciones de creación,
mantenimiento y consulta sobre ficheros y bases de datos. Dentro de este
campo estarían aplicaciones de gestión empresarial, como programas de
nominas, contabilidad facturación, control de inventario, etc. Lenguajes aptos
para este tipo de aplicaciones son COBOL y SQL.

 Aplicaciones de tratamiento de textos.


Estas aplicaciones están asociadas al manejo de textos en lenguaje natural. Un
lenguaje muy adecuado para este tipo de aplicaciones es el C.
 Aplicaciones en inteligencia artificial.
Dentro de este campo, destacan las aplicaciones en sistemas expertos, juegos,
visión artificial, robótica. Los lenguajes más populares dentro del campo de la
inteligencia artificial son LISP y PROLOG

 Aplicaciones de programación de sistemas.


En este campo se incluirían la programación de software de interfaz entre el
usuario y el hardware, como son los módulos de un sistema operativo y los
traductores. Tradicionalmente para estas aplicaciones se utilizaba el
Ensamblador, no obstante en la actualidad se muestran muy adecuados los
lenguajes ADA, MODULA-2 y C.

 Lenguajes de Internet.
HTML, JAVA, Perl, PHP, etc

2.4. TIPOS DE LENGUAJE DE PROGRAMACIÓN EN FUNCIÓN AL ESTILO


DE PROGRAMAR

 Lenguajes imperativos
 Lenguajes funcionales
 Lenguajes lógicos (declarativos)
 Lenguajes orientados a objetos
 Lenguajes con concurrencia

2.5. LENGUAJES IMPERATIVOS

En este tipo de lenguajes, cuyo origen está ligado a la propia arquitectura de von
Neumann, la arquitectura consta de una secuencia de celdas, llamadas memoria,
en la cual se pueden guardar en forma codificada, lo mismo datos que
instrucciones; y de un procesador, el cual es capaz de ejecutar de manera
secuencial una serie de operaciones, principalmente aritméticas y booleanas,
llamadas comandos. En general, un lenguaje imperativo ofrece al programador
conceptos que se traducen de forma natural al modelo de la máquina.Los
lenguajes imperativos más destacados de la historia han sido: FORTRAN, Algol,
Pascal, C, Modula-2, Ada
El programador, al utilizar un lenguaje imperativo, por lo general tiene que
traducir la solución abstracta del problema a términos muy primitivos, cercanos a
la máquina. La distancia entre el nivel del razonamiento humano y lo expresable
por los lenguajes imperativos causa que sus programas sean más "comprensibles"
para la máquina que para el hombre. Esta desventaja para nosotros, reflejada en la
dificultad que tenemos al construir programas en un lenguaje imperativo, se
vuelve una ventaja en el momento de la generación del código. El programa está
expresado en términos tan cercanos a la máquina, que el código generado es
relativamente parecido al programa original, lo que permite cierta eficiencia en la
ejecución.

Ejemplo:
Este sería el código de un programa que determina el factorial de un número en un
lenguaje imperativo inventado:
procedimiento factorial(entero n){
entero resultado = 1;
mientras (n > 0) {
resultado = resultado * n;
n = n - 1;
}
devuelve resultado;
}
Este procedimiento (o función) recibe un número entero n. Declara una variable
resultado que será el resultado final a devolver. Inicialmente, tiene como valor el
1. Después llega una estructura de control denominada bucle, que se ejecuta
mientras la condición expresada entre los paréntesis (n > 0) sea cierta. Dentro del
bucle se multiplica la variable resultado por n y el valor se deja de nuevo en
resultado. La siguiente sentencia (n = n - 1) es necesaria para ir haciendo el
factorial, así como para salir en algún momento del bucle. Por último, tras salir del
bucle ya podemos devolver el valor final, que estará en la variable resultado.
Nótese que, si en un principio, la variable n es 0, no se entrará en el bucle al no ser
cierta la condición, por lo que pasaría directamente a devolver la variable
resultado, que tiene valor inicial 1 (0! = 1).

2.6. LENGUAJES FUNCIONALES

2.6.1.CONCEPTO MATEMÁTICO DE FUNCIÓN.


Puede ser definida como una correspondencia entre dos variables, una
llamada variable dependiente y otra llamada variable dependiente. Veamos la
siguiente notación:
y = f(x)

Donde:
y: Es la variable dependiente de la función. Se le llama dependiente porque
para que pueda tomar un valor, depende de los valores que pueda tomar la
variable x. También podemos decir que “y esta en función de x”.
x: Es la variable independiente de la función. Se dice que es independiente ya
que puede tomar los valores que quiera y no hay nada que se lo impida; o sea,
tiene independencia.
f: Se puede decir que es el procedimiento o ecuación que tomará a x para
devolverle un valor a y.
Veamos una función muy común:
y = x2 + x

La función anterior tiene a y como variable dependiente y a x como variable


independiente, y el procedimiento es elevar a x (variable independiente) al
cuadrado y sumarle x. Por cada valor que tome x, a y le corresponderá otro.
También podemos tener una función con más de una variable dependiente...
y = x + z – 1 / (w + 3)

En el sistema anterior podemos encontrar que la variable dependiente (en este


caso y) esta en función de 3 variables independientes (en este caso x, z, w).
Generalmente en las matemáticas las variables dependientes están
representadas por la letra y, aunque también las podemos representar con letras
como z, w, ó x, ó g, etc. siempre y cuando sean diferentes de las variables
independientes; así mismo, la o las variables independientes se pueden
representar de la misma forma, teniendo en cuenta que no deben ser iguales a
las dependientes.

2.6.2.CONCEPTO DE LENGUAJES FUNCIONALES.


Los matemáticos desde hace un buen tiempo están resolviendo problemas
usando el concepto de función. Una función convierte ciertos datos en
resultados. Si supiéramos cómo evaluar una función, usando la computadora,
podríamos resolver automáticamente muchos problemas. Así pensaron algunos
matemáticos, que no le tenían miedo a la máquina, e inventaron los lenguajes
de programación funcionales. Además, aprovecharon la posibilidad que tienen
las funciones para manipular datos simbólicos, y no solamente numéricos, y la
propiedad de las funciones que les permite componer, creando de esta manera,
la oportunidad para resolver problemas complejos a partir de las soluciones a
otros más sencillos. También se incluyó la posibilidad de definir funciones
recursivamente.
Un lenguaje funcional ofrece conceptos que son muy entendibles y
relativamente fáciles de manejar para todos los que no se durmieron en las
clases de matemáticas. El lenguaje funcional más antiguo, y seguramente el
más popular hasta la fecha, es LISP, diseñado por McCarthy en la segunda
mitad de los años 50. Su área de aplicación es principalmente la Inteligencia
Artificial. En la década de los 80 hubo una nueva ola de interés por los
lenguajes funcionales, añadiendo la tipificación y algunos conceptos modernos
de modularización y polimorfismo, como es el caso del lenguaje ML.
Programar en un lenguaje funcional significa construir funciones a partir de las
ya existentes. Por lo tanto es importante conocer y comprender bien las
funciones que conforman la base del lenguaje, así como las que ya fueron
definidas previamente. De esta manera se pueden ir construyendo aplicaciones
cada vez más complejas. La desventaja de este modelo es que resulta bastante
alejado del modelo de la máquina de Von Neumann y, por lo tanto, la
eficiencia de ejecución de los intérpretes de lenguajes funcionales no es
comparable con la ejecución de los programas imperativos precompilados.
Para remediar la deficiencia, se está buscando utilizar arquitecturas paralelas
que mejoren el desempeño de los programas funcionales, sin que hasta la
fecha estos intentos tengan un impacto real importante.

2.6.3.CATEGORÍAS DE LENGUAJES FUNCIONALES.


Existen dos categorías de lenguajes funcionales: los funcionales puros y los
híbridos, La diferencia entre ambos estriba en que los lenguajes funcionales
híbridos son menos dogmáticos que los puros, al admitir conceptos tomados de
los lenguajes imperativos, como las secuencias de instrucciones o la
asignación de variables. En contraste, los lenguajes funcionales puros tienen
una mayor potencia expresiva, conservando a la vez su transparencia
referencial, algo que no se cumple siempre con un lenguaje funcional híbrido.
Entre los lenguajes funcionales puros, cabe destacar a Haskell y Miranda. Los
lenguajes funcionales híbridos más conocidos son Lisp, Scheme, Ocaml y
Standard ML (estos dos últimos, descendientes del lenguaje ML).

2.6.4.PROBLEMAS DEL MODELO IMPERATIVO


Los programas escritos en lenguajes de programación tradicionales
(imperativo) como Pascal, C, ADA, etc. forman una abstracción de la máquina
de Von-Neumann caracterizada por:
 Memoria Principal para almacenamiento de datos y código máquina.
 Unidad Central de Proceso con una serie de registros de almacenamiento
temporal y un conjunto instrucciones de cálculo aritmético, modificación
de registros y acceso a la Memoria Principal.

Los programas imperativos están formados por una serie de datos globales y
un conjunto de instrucciones ó código. Estos dos elementos forman una
abstracción de los datos y código de la memoria principal.
El programador trabaja en un nivel cercano a la máquina lo que le permite
generar programas eficientes. Con esta proximidad aparece, sin embargo, una
dependencia entre el algoritmo y la arquitectura que impide, por ejemplo,
utilizar algoritmos programados para arquitecturas secuenciales en
arquitecturas paralelas.
Los algoritmos escritos en lenguajes imperativos se expresan mediante una
secuencia de instrucciones que modifican el estado de un programa accediendo
a los datos globales de la memoria. En este punto es donde empiezan los
problemas:

Ejemplo
Program prueba;
var flag:boolean;
function f (n: integer):integer;
begin
flag:=not flag;
if flag then f:=n;
else f:=2*n;
end;
........
--Programa principal
begin
flag:=true;
......
write(f(1));  retorna 2
write(f(1));  retorna 1
.......
write(f(1) + f(2));  retorna 4
write(f(2) + f(1));  retorna 5

En el primer caso la expresión f(1) retorna valores diferentes dependiendo de


la secuencia de ejecución y en el segundo no se cumplen propiedades
matemáticas simples tales como la conmutatividad. Estos ejemplos ponen en
evidencia que ciertas características de los lenguajes imperativos tales como la
asignación pueden traer consigo efectos laterales inesperados que oscurecen la
semántica del programa; en consecuencia se hace difícil demostrar que los
programas cumplen con los requerimientos especificados y que estén libres de
errores.
Este y otros problemas son inherentes al modelo computacional utilizado, por
ende una solución factible de ser aplicada puede ser cambiar el modelo
computacional. Entre otras alternativas se encuentran el modelo funcional o
aplicativo cuyo objetivo es describir los problemas mediante funciones
matemáticas sin efectos laterales, y el modelo lógico o declarativo que
describe los problemas mediante relaciones entre objetos o entidades.

2.7. LENGUAJES LÓGICOS (DECLARATIVOS)

Otra forma de razonar para resolver problemas en matemáticas se fundamenta en


la lógica de primer orden. El conocimiento básico de las matemáticas se puede
representar en la lógica en forma de axiomas, a los cuales se añaden reglas
formales para deducir cosas verdaderas (teoremas) a partir de los axiomas. Gracias
al trabajo de algunos matemáticos, de finales de siglo pasado y principios de éste,
se encontró la manera de automatizar computacionalmente el razonamiento lógico
-particularmente para un subconjunto significativo de la lógica de primer orden-
que permitió que la lógica matemática diera origen a otro tipo de lenguajes de
programación, conocidos como lenguajes lógicos. También se conoce a estos
lenguajes, y a los funcionales, como lenguajes declarativos, porque el
programador, parar solucionar un problema, todo lo que tiene que hacer es
describirlo vía axiomas y reglas de deducción en el caso de la programación lógica
y vía funciones en el caso de la programación funcional.
En los lenguajes lógicos se utiliza el formalismo de la lógica para representar el
conocimiento sobre un problema y para hacer preguntas que, si se demuestra que
se pueden deducir a partir del conocimiento dado en forma de axiomas y de las
reglas de deducción estipuladas, se vuelven teoremas. Así se encuentran
soluciones a problemas formulados como preguntas. Con base en la información
expresada dentro de la lógica de primer orden, se formulan las preguntas sobre el
dominio del problema y el intérprete del lenguaje lógico trata de encontrar la
respuesta automáticamente. El conocimiento sobre el problema se expresa en
forma de predicados (axiomas) que establecen relaciones sobre los símbolos que
representan los datos del dominio del problema.
En el caso de la programación lógica, el trabajo del programador se restringe a la
buena descripción del problema en forma de hechos y reglas. A partir de ésta se
pueden encontrar muchas soluciones dependiendo de como se formulen las
preguntas (metas), que tienen sentido para el problema. Si el programa está bien
definido, el sistema encuentra automáticamente las respuestas a las preguntas
formuladas. En este caso ya no es necesario definir el algoritmo de solución, como
en la programación imperativa, en cambio, lo fundamental aquí es expresar bien el
conocimiento sobre el problema mismo. En programación lógica, al igual que en
programación funcional, el programa, en este caso los hechos y las reglas, están
muy alejados del modelo von Neumann que posee la máquina en la que tienen que
ser interpretados; por lo tanto, la eficiencia de la ejecución no puede ser
comparable con la de un programa equivalente escrito en un lenguaje imperativo.
Sin embargo, para cierto tipo de problemas, la formulación del programa mismo
puede ser mucho más sencilla y natural (para un programador experimentado, por
supuesto).

 PROLOG
Prolog, proveniente del francés Programation et Logique, sus orígenes se
remotan a los inicios de la década de los 70 con los trabajos del grupo de A.
Colmerauer en Marsella, Francia. Es un lenguaje de programación lógico e
interpretado, bastante popular en el medio de investigación en Inteligencia
Artificial.

 Historia
Se trata de un lenguaje de programación ideado a principios de los años 70
en la universidad de Aix-Marseille por los profesores Alain Colmerauer y
Phillipe Roussel. Inicialmente se trataba de un lenguaje totalmente
interpretado hasta que, a mediados de los 70, David H.D. Warren
desarrolló un compilador capaz de traducir Prolog en un conjunto de
instrucciones de una máquina abstracta denominada Warren Abstract
Machine, o abreviadamente, WAM. Desde entonces Prolog es un lenguaje
semi-interpretado.
Prolog se enmarca en el paradigma de los lenguajes lógicos, lo que lo
diferencia enormemente de otros lenguajes más populares tales como
Fortran, Pascal, C.
 Retroseguimiento
En todos los mencionados, las instrucciones se ejecutan normalmente en
orden secuencial, es decir, una a continuación de otra, en el mismo orden
en que están escritas, que sólo varía cuando se alcanza una instrucción de
control (un bucle, una instrucción condicional o una transferencia).
Los programas en Prolog se componen de cláusulas de Horn que
constituyen reglas del tipo "modus ponendo ponens", es decir, "Si es
verdad el antecedente, entonces es verdad el consecuente". No obstante, la
forma de escribir las cláusulas de Horn es al contrario de lo habitual.
Primero se escribe el consecuente y luego el antecedente. El antecedente
puede ser una conjunción de condiciones que se denomina secuencia de
objetivos. Cada objetivo se separa con una coma y puede considerarse
similar a una instrucción o llamada a procedimiento de los lenguajes
imperativos. En Prolog no existen instrucciones de control. Su ejecución se
basa en dos conceptos: la unificación y el backtracking.
Gracias a la unificación, cada objetivo determina un subconjunto de
cláusulas susceptibles de ser ejecutadas. Cada una de ellas se denomina
punto de elección. Prolog selecciona el primer punto de elección y sigue
ejecutando el programa hasta determinar si el objetivo es verdadero o
falso.
En caso de ser falso entra en juego el 'backtracking', que consiste en
deshacer todo lo ejecutado situando el programa en el mismo estado en el
que estaba justo antes de llegar al punto de elección. Entonces se toma el
siguiente punto de elección que estaba pendiente y se repite de nuevo el
proceso. Todos los objetivos terminan su ejecución bien en éxito
("verdadero"), bien en fallo ("falso").

 Expresiones
Prolog cuenta con operadores para la unificación y comparación sea con
evaluación o sea simbólica como lo siguiente:
 X is Y %unificación con evaluación.
 X=Y %unificación simbólica
 X=:=Y %comparación con evaluación
 X==Y %comparación simbólica.
 Listas
La representación de hechos simples no es lo común en la clasificación de
elementos, sino que se agrupan los elementos de un mismo tipo en una
lista.

Ejemplo:
% Si queremos hallar la longitud de una lista.
% La longitud de una lista vacia es 0.
% La longitud de cualquier lista es la longitud de la cola + 1.

longitud([],0).
longitud([H|T],N):-longitud(T,N0), N is N0 + 1.
?- longitud([a,b,c],L).
3
?- longitud([a,b,c],4).
No
% Si queremos determinar si un elemento es pertenece a una lista.
% El elemento pertenece a la lista si coincide con la cabeza de la lista.
% El elemento pertenece a la lista si es se encuentra en la cola de la lista.
pertenece(X,[X|_]).
pertenece(X,[_|R]):- pertenece(X,R).
?- pertenece(b,[a,b,c]).
Yes
?- pertenece(b,[a,[b,c]]).
No
?- pertenece([b,c],[a,[b,c]]).
Yes
% Si queremos eliminar un elemento de la lista.
% Si X es la cabeza de la lista, la cola T es la lista sin X
% Si X no es la cabeza de la lista, conservamos la cabeza de la lista
% como parte de la respuesta y continuamos eliminando X de la cola T.
elimina (X,[X|T],T).
elimina (X,[H|T],[H|T1]):- elimina (X,T,T1).
?- elimina(1,[1,2,3,4],R).
R = [2,3,4]
?- elimina(1,R,[2,3]).
R = [1, 2, 3]
R = [2, 1, 3]
R = [2, 3, 1]
% Si queremos calcular la inversa de una lista.
% La inversa de una lista vacia es una lista vacia.
% La inversa de H|T es la inversa de T concatenada con H.
inversa([],[]).
inversa([H|T],L):- inversa(T,R), concatenar(R,[H],L).
?- inversa([a,b,c,d],[d,c,b,a]).
Yes

2.8. LENGUAJES ORIENTADOS A OBJETOS

A mediados de los años 60 se empezó a vislumbrar el uso de las computadoras


para la simulación de problemas del mundo real. Pero el mundo real está lleno de
objetos, en la mayoría de los casos complejos, los cuales difícilmente se traducen
a los tipos de datos primitivos de los lenguajes imperativos. Así es que a dos
noruegos, Dahl y Nygaard, se les ocurrió el concepto de objeto y sus colecciones,
llamadas clases de objetos, que permitieron introducir abstracciones de datos a los
lenguajes de programación. La posibilidad de reutilización del código y sus
indispensables modificaciones, se reflejaron en la idea de las jerarquías de
herencia de clases. A ellos también les debemos el concepto de polimorfismo
introducido vía procedimientos virtuales. Todos estos conceptos fueron
presentados en el lenguaje Simula 67, desde el año 1967. Aunque pensado como
lenguaje de propósito general, Simula tuvo su mayor éxito en las aplicaciones de
simulación discreta, gracias a la clase SIMULATION que facilitaba
considerablemente la programación.
La comunidad informática ha tardado demasiado en entender la utilidad de los
conceptos básicos de Simula 67, que hoy identificamos como conceptos del
modelo de objetos. Tuvimos que esperar hasta los años 80 para vivir una
verdadera ola de propuestas de lenguajes de programación con conceptos de
objetos encabezada por Smalltalk, C++, Eiffel, Modula-3, Ada 95 y terminando
con Java. La moda de objetos se ha extendido de los lenguajes de programación a
la Ingeniería de Software
La reutilización de clases previamente probadas en distintos sistemas también es
otro punto a favor. Sin embargo, el modelo de objetos, a la hora de ser interpretado
en la arquitectura von Neumann conlleva un excesivo manejo dinámico de
memoria debido a la constante creación de objetos, así como a una carga de
código fuerte causada por la constante invocación de métodos. Por lo tanto, los
programas en lenguajes orientados a objetos siempre pierden en eficiencia, en
tiempo y memoria, contra los programas equivalentes en lenguajes imperativos.
Para consolarnos, los expertos dicen que les ganan en la comprensión de código.

 Características fundamentales de la POO:


1. Encapsulamiento: Es la ocultación de información. Significa mantener la
información dentro del objeto y mantenerlo como una caja negra. Puede
ser accedida por métodos.
2. Abstracción: Es la capacidad de aislar y encapsular la información del
diseño y la ejecución. Es la capacidad para identificar atributos y métodos.
Herencia: Es la propiedad que permite a los objetos crearse a partir de
otros objetos.
3. Polimorfismo: Es la capacidad de que diferentes objetos reaccionen de
distinta forma a un mismo mensaje.

2.9. LENGUAJES CON CONCURRENCIA

La necesidad de ofrecer concurrencia en el acceso a los recursos computacionales


se remonta a los primeros sistemas operativos. Mientras que un programa
realizaba una operación de entrada o salida otro podría gozar del tiempo del
procesador para sumar dos números, por ejemplo. Aprovechar al máximo los
recursos computacionales fue una necesidad apremiante, sobre todo en la época en
que las computadoras eran caras y escasas; el sistema operativo tenía que ofrecer
la ejecución concurrente y segura de programas de varios usuarios, que desde
distintas terminales utilizaban un solo procesador, y así surgió la necesidad de
introducir algunos conceptos de programación concurrente para programar los
sistemas operativos.
Posteriormente, cuando los procesadores cambiaron de tamaño y de precio, se
abrió la posibilidad de contar con varios procesadores en una máquina y ofrecer el
procesamiento en paralelo, es decir, procesar varios programas al mismo tiempo.
Esto dio el impulso a la creación de lenguajes que permitían expresar el
paralelismo. Finalmente, llegaron las redes de computadoras, que también ofrecen
la posibilidad de ejecución en paralelo, pero con procesadores distantes, lo cual
conocemos como la programación distribuida.
Históricamente encontramos en la literatura soluciones conceptuales y
mecanismos tales como: semáforos, regiones críticas, monitores, envío de
mensajes (CSP), llamadas a procedimientos remotos (RPC), que posteriormente se
incluyeron como partes de los lenguajes de programación en Concurrent Pascal,
Modula, Ada, OCCAM, y últimamente en Java.
Uno de los ejemplos más importantes es el modelo de envío de mensajes de CSP
de Hoare, para las arquitecturas paralelas y distribuidas, el cual no solamente
fructificó en una propuesta del lenguaje de programación OCCAM, sino dio
origen a una nueva familia de procesadores, llamados "transputers", que
fácilmente se componen en una arquitectura paralela.
Es difícil evaluar las propuestas existentes de lenguajes para la programación
concurrente, paralela y distribuida. Primero, porque los programadores están
acostumbrados a la programación secuencial y cualquier uso de estos mecanismos
les dificulta la construcción y el análisis de programas. Por otro lado, este tipo de
conceptos en el pasado fue manejado principalmente a nivel de sistemas
operativos, protocolos de comunicación, etcétera, donde la eficiencia era crucial, y
por lo tanto no se utilizaban lenguajes de alto nivel para la programación. Hoy en
día, la programación de sistemas complejos tiene que incluir las partes de
comunicaciones, programación distribuida y concurrencia. Esto lo saben los
creadores de los lenguajes más recientes, que integran conceptos para manejar: los
hilos de control, comunicación, sincronización y no determinismo; el hardware y
las aplicaciones se los exigen.
2.10.EVOLUCIÓN DE LOS LENGUAJES DE PROGRAMACIÓN
DECLARATIVOS

Gráfico Nº 1: Evolución de los lenguajes de programación Declarativos


2.11.EVOLUCIÓN DE LOS LENGUAJES DE PROGRAMACIÓN ORIENTADO
A OBJETOS E IMPERATIVOS

Gráfico Nº 2: Evolución de los lenguajes de programación OO e Imperativos


CAPÍTULO III: CONCEPTOS EN LOS LENGUAJES DE
PROGRAMACIÓN

3.1. ¿QUÉ ES LO QUE CONSTITUYE UN BUEN LENGUAJE?

3.1.1.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.
3.1.2.ESTANDARIZACIÓN DE LOS LENGUAJES
Los estándares son en general de dos clases:

 Estándares patentados: Son las definiciones elaboradas por la


compañía que desarrolló el lenguaje y que es su propietaria.
 Estándares de consenso: 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..

3.2. SINTAXIS DE LENGUAJES DE PROGRAMACIÓN

La sintaxis suministra información significativa que se necesita para entender un


programa y proporciona información imprescindible para la traducción del
programa fuente a un programa objeto.
Se necesita algo más que sólo estructuras sintácticas para la plena descripción de
un lenguaje de programación. Otros atributos bajo el término general de
semántica, como el uso de declaraciones, operaciones, control de secuencia y
entornos de refinamiento, afectan a una variable y no siempre están determinados
por reglas de sintaxis.

CRITERIOS GENERALES DE SINTAXIS


El propósito primordial de la sintaxis es proveer una notación para la
comunicación entre el programador y el procesador de lenguajes de programación.
Los detalles de la sintaxis se eligen en gran medida con base en criterios
secundarios, como:

 Legibilidad: Un programa es legible si la estructura subyacente del algoritmo


y los datos que el programa representa quedan de manifiesto al inspeccionar el
texto del programa.
 Facilidad de escritura: Suele hallarse en conflicto con las características que
facilitan su lectura. Este atributo mejora a través del uso de estructuras
sintácticas concisas y regulares.
Una sintaxis es redundante si comunica el mismo elemento de información en más
de una forma. Cierta redundancia es útil en la sintaxis de lenguajes de
programación porque facilita la lectura del programa y también permite revisar en
busca de errores durante la traducción.
 Facilidad de verificación: Tiene relación con la legibilidad y facilidad de
escritura. Se necesitan técnicas que permitan comprobar que el programa es
matemáticamente correcto.
 Facilidad de traducción: Los programas deben ser fáciles de traducir a una
forma ejecutable. Está relacionado con las necesidades del traductor que
procesa el programa escrito.
La traducción de los programas se dificulta conforme aumenta el número
de construcciones sintácticas especiales.
 Carencia de ambigüedad: Una construcción ambigua permite dos o más
interpretaciones distintas. El problema de ambigüedad surge por lo común no
en la estructura de elementos individuales del programa, sino en la
interacción entre diferentes estructuras (Ej. Condicionales).

3.3. TIPOS DE DATOS

 Numéricos: Entero, Real.


 Booleano.
 Carácter.
 Definidos por el usuario: tipos especificados por el usuario como limitaciones
de los básicos.
 Enumerados, subrangos, modulares…
 Arrays: son tipos con tamaño fijo y todos los elementos del mismo tipo.
 String está definido e muchos lenguajes como un array de caracteres.
 Registros: Es una estructura de datos formada por un numero fijo de
componentes de distinto tipo.
 Punteros: almacena la dirección de memoria de otro objeto de datos.
 Referencia: no se pueden manejar directamente, lo hace el compilador.
 Tipo función: se considera un tipo por poderse incluir en una expresión, y
suele ir acompañado de su descriptor.
3.4. ABSTRACCIÓN

La abstracción nos permite simplificar el análisis y resolución de un problema


separando las características que son relevantes de aquellas que no lo son. La
relevancia dependerá fuertemente del contexto. Un ejemplo típico de abstracción
es una jerarquía de objetos determinada por sus características comunes.
Aunque la abstracción es un concepto general aplicable a cualquier campo
nosotros estamos interesados en la abstracción que proporciona un lenguaje de
programación. En este sentido la aportación más importante ha sido el desarrollo
de los lenguajes de alto nivel, éstos nos permiten utilizar ciertas construcciones de
alto nivel en lugar de una secuencia de instrucciones máquina. Aún así, el nivel de
abstracción proporcionado por un lenguaje de programación resulta insuficiente.
Podemos aumentar el nivel de abstracción haciendo que el lenguaje de
programación incluya mecanismos que permitan construir al usuario sus propias
abstracciones. El mecanismo más común para tal fin es el uso de funciones y
procedimientos, aunque existen otros mecanismos.
Los lenguajes de programación orientados a objetos ofrecen un cada vez más
amplio abanico de estructuras de datos organizadas jerárquicamente (listas, pilas,
colas, etc.) junto con primitivas para manejarlas agrupadas en lo que
habitualmente se conoce como clase, además, el usuario puede definir nuevas
clases

3.5. ABSTRACCIÓN EN PROGRAMACIÓN

Cuando la computación estaba en su infancia, la mayoría de los programas se


escribían en ensamblador por un programador, y no se considerarían como grandes
programas según los estándares de hoy en día. Aún así, en la medida en que los
programas se hicieron más complejos, los programadores encontraron más
dificultades para recordar toda la información que necesitaban para desarrollar o
eliminar errores de sus programas.
Aunque la introducción de lenguajes de alto nivel resolvió algunas dificultades, al
mismo tiempo incrementó las expectativas de la gente acerca de lo que podría
hacer una computadora, de tal forma que sólo provocó la aparición de un mayor
número de problemas. Así, a medida que se intentaban resolver problemas más
complejos por medio de una computadora, mayor era la tarea que debía desarrollar
el programador, rebasando la capacidad incluso de los mejores programadores. En
consecuencia, comenzaron a proliferar equipos de programadores que trabajaban
conjuntamente para emprender grandes tareas de programación.
Se observó entonces un problema que aún hoy no se ha abordado de forma
completamente satisfactoria: los sistemas de software son sistemas complejos con
un alto grado de interconexión. La interconexión es la dependencia de una parte
del código de otra sección de código.
Surgieron así diversas técnicas y mecanismos para tratar de reducir el problema de
la complejidad. La abstracción es uno de estos mecanismos y es posiblemente el
más importante de todos. El mecanismo de abstracción permite descomponer de
forma productiva un problema mediante el cambio del nivel de detalle a
considerar, pero es algo intangible. Surge por tanto la necesidad de describirla de
alguna forma, la especificación es esta descripción. La abstracción funcional; es
decir, la idea de crear procedimientos y funciones e invocarlos mediante un
nombre, fue uno de los primeros mecanismos de abstracción que se usaron
ampliamente en los lenguajes de programación. Los procedimientos permitían que
las tareas que se ejecutaban varias veces, fueran agrupadas en un lugar para
reutilizarlas, en vez de duplicar el código una y otra vez. Es este tipo de
abstracción lo importante es qué hace la función y no importa cómo lo hace. El
usuario del procedimiento solo necesita conocer la especificación de la abstracción
y puede ignorar el resto de detalles.

3.6. CLASES DE ABSTRACCIÓN

3.6.1.ABSTRACCIÓN DE CONTROL
Hace referencia a los mecanismos necesarios para representar el flujo de
control de un programa, evitando detalles de bajo nivel. Se subdivide en: nivel
de sentencias básicas y a nivel de subprogramas o unidades de programa.
 Sentencias condicionales: If/else, alternativa múltiple (swith).
 Sentencias iterativas: For, While y repeat.
Abstracción procedimental
 Subprograma: conjunto de líneas de código con cierta independencia del
resto.
 Procedimientos: subprogramas que tienen de 0 a n parámetros, sin tipo,
no pueden ser usados en expresiones y pueden devolver de 0 a n resultados
distintos.
 Funciones: pueden tener de 0 a n argumentos de entrada, devuelve solo 1
resultado siempre. Tiene tipo y se puede usar en una expresión.

Paso de parámetros:
 Formas de paso de parámetros:
 Por referencia: se pasa la dirección de memoria del parámetro (E/S).
 Por copia:
 Copia por valor: se crea una var temporal copiándole el valor del
parámetro.(E)
 Copia por resultado: se crea una var local, y al acabar se devuelve el
resultado (S)
 Copia por valor-resultado: se crea una var local pasándole el valor, con
la que se trabaja, y al acabar se devuelve el resultado
 Formas de asignar los argumentos:
 Por posición: se asignan los parámetros formales con los reales por
orden.
 Por nombre: en la llamada se añade el nombre del parámetro formal.
 Por defecto: toma un valor por defecto especificado en compilación si
no se le da ninguno.
Ejemplo:
Void ordenar (int a[],int n) el usuario no necesita conocer los detalles de
cómo se realiza el ordenamiento, solo debe suministrar un arreglo y su tamaño
y recibirá el arreglo ordenado (en un orden predeterminado como ascendente)
3.6.2.ABSTRACCIÓN DE DATOS.
Una abstracción de datos (tipo de dato o tipo abstracto de dato) es un nuevo
tipo de dato más un conjunto de operaciones que permiten manipular los
objetos de dicho tipo. En esta definición juega un papel importante el uso de la
palabra objeto en lugar de variable. La diferencia entre ambos conceptos se
explicará más adelante.
La correcta utilización de los tipos abstractos de datos (TADs en lo sucesivo)
en el diseño de programas da lugar a programas de gran modularidad y
calidad:
 Son más legibles
 Son más fáciles de interpretar
 Son más fáciles de modificar

3.7. TIPOS ABSTRACTOS DE DATOS (TADS)

Es una estructura de datos junto a las instrucciones para manejarlo, haciendo


invisible ciertas partes al usuario programador. Permite la asociación de una
representación con sus operaciones concretas en una unidad adecuada de lenguaje
que incorpora los nuevos tipos y el ocultamiento de la representación del nuevo
tipo a las unidades que lo usan.
Tipos genéricos, genericidad: consiste en que las entidades de programa puedan
trabajar con independencia de los tipos de datos concretos. Para usarse hay que
instanciarlos.

3.8. LENGUAJES DE PROGRAMACIÓN Y TADS

La abstracción de datos es una técnica de diseño de programas que promete un


alto grado de modularidad y un desarrollo independiente de la implementación de
dicha abstracción y de la aplicación del programa. Por tratarse de una técnica de
diseño, su utilización es en su mayor parte independiente del lenguaje de
programación, sin embargo, el uso e implementación de TADs con lenguajes de
programación que no los soportan convenientemente puede dar lugar a
deficiencias en algunos de los aspectos siguientes:
 Ocultación de la representación. Los lenguajes que no soportan TADs no
pueden chequear el buen uso de la abstracción de datos, dada la imposibilidad
de ocultar a los usuarios de la abstracción la representación de los objetos
 Inicialización de las estructuras de datos. Los lenguajes que no soportan
TADs no disponen de un procedimiento automático de inicialización de las
estructuras de datos que se utilizan para representar a los objetos del TAD.
Esto supone que al principio de los programas que utilicen un TAD debe
invocarse a una acción para inicializar convenientemente dichas estructuras
(operación no relacionada con los objetos
 Compilación independiente. En los lenguajes que soportan TADs, el código
de estos se puede separar del código de los programas de aplicación y
compilarlos independientemente. En todo caso, esta facilidad se tiene en
cualquier lenguaje que soporte la compilación independiente.
 Parametrización de tipos. En los lenguajes que no soportan TADs no se
puede parametrizar una definición de tipo con otro tipo; es decir, no se pueden
realizar abstracciones (funcionales o de datos) de tipos desconocidos.
 Abstracciones polimórficas. En los lenguajes que no soportan TADs no se
pueden construir abstracciones que puedan ser utilizadas por objetos de
diferentes tipos.
 Los tipos definidos por el usuario no se comportan como los predefinidos
del lenguaje. Así, por ejemplo, un objeto de tipo Racional no se crea por
completo al declararlo siendo necesario realizar una llamada posterior a la
operación Crear_Racional para inicializarlo convenientemente.

Esta última deficiencia provoca que en un lenguaje de programación que no


soporte TADs puedan existir objetos cuya representación no sea válida sin que ello
sea detectado por el compilador. Esto obliga al usuario a utilizar escrupulosamente
el TAD, o bien, al desarrollador de la abstracción de datos a realizar
implementaciones de éste que tuvieran en cuenta éste hecho.
3.9. LENGUAJES DE PROGRAMACIÓN QUE DEBERÍAS APRENDER

3.9.1.PHP
PHP usa una mezcla entre interpretación y compilación para intentar ofrecer a
los programadores la mejor mezcla entre rendimiento y flexibilidad.
PHP compila para tu codigo una serie de instrucciones (llamadas opcodes)
siempre que estas son accedidas. Estas instrucciones son entonces ejecutadas
una por una hasta que el script termina. Esto es diferente a la manera
convencional de compilacion de lenguajes como C++ donde el código es
compilado a código ejecutable que es despues ejecutado. Php es recompilado
cada vez que se solicita un script. Una ventaja importante de interpretar el
código es que toda la memoria usada por tu código es manejada por PHP, y el
lenguaje automáticamente vacía esta memoria cuando el script finaliza. Esto
significa que tu no tienes que preocuparte de las conexiones a la base de datos,
porque PHP lo hará por ti.
¿Por qué deberías aprenderlo?
Es uno de los lenguajes de programación más populares, la gran fluidez y
rapidez de sus scripts y su prometedor futuro, desarrollar aplicaciones Webs
utilizando lenguajes como C o COBOL son cosas del pasado.

3.9.2.C#
C# es un lenguaje de propósito general orientado a objetos creado por
Microsoft para su plataforma .NET.
Su sintaxis básica deriva de C/C++ y utiliza el modelo de objetos de la
plataforma .NET el cual es similar al de Java aunque incluye mejoras
derivadas de otros lenguajes. C# fue diseñado para combinar el control a bajo
nivel de lenguajes como C y la velocidad de programación de lenguajes como
Visual Basic.
¿Por qué deberías aprenderlo?
Es una parte esencial de la plataforma .Net, C# combina los mejores elementos
de múltiples lenguajes de amplia difusión como C++, Java, Visual Basic o
Delphi. De hecho, su creador Anders Heljsberg fue también el creador de
muchos otros lenguajes y entornos como Turbo Pascal, Delphi o Visual J++.
La idea principal detrás del lenguaje es combinar la potencia de lenguajes
como C++ con la sencillez de lenguajes como Visual Basic, y que además la
migración a este lenguaje por los programadores de C/C++/Java sea lo más
inmediata posible.

3.9.3.AJAX
AJAX no es un lenguaje exactamente su nombre viene dado por el acrónimo
de Asynchronous JavaScript And XML y es posiblemente la mayor novedad
en cuanto a programación web en estos últimos años.
El corazón de Ajax es el objeto XMLHttpRequest que nos permite realizar una
conexión al servidor y al enviarle una petición y recibir la respuesta que
procesaremos en nuestro código Javascript, estamos hablando del verdadero
motor de Ajax, por ejemplo gracias a este objeto podemos desde una página
HTML leer datos de una web o enviar datos de un formulario sin necesidad de
recargar la página.
¿Por qué deberías aprenderlo?
La demanda de AJAX no sólo es amplía sino que de calidad debido a la
dificultad de aprendizaje que conlleva, si la herramienta de Microsoft, Atlas,
destinada a la realización de aplicaciones AJAX tiene éxito puede supone un
aumento en la demanda de esta tecnología.

3.9.4.JAVASCRIPT
Se trata de un lenguaje de programación del lado del cliente, porque es el
navegador el que soporta la carga de procesamiento. Gracias a su
compatibilidad con la mayoría de los navegadores modernos, es el lenguaje de
programación del lado del cliente más utilizado.
¿Por qué deberías aprenderlo?
La razón de mayor peso es que es utilizado por millones de páginas webs para
validar formularios, crear cookies, detectar navegadores y mejorar el diseño,
su fácil aprendizaje lo hace un lenguaje muy demandado.
3.9.5.PERL
Perl es la alternativa más popular a PHP, seguramente porque es el lenguaje
más antiguo tambien dentro de las alternativas. En internet nos encontramos
numerosos recursos que utilizan Perl, muchos de las aplicaciones "open
source" requieren tener Perl instalado correctamente. Perl tiene una ventaja y
es que es muy flexible, y tambien tiene un gran cantidad de modulos ya
escritos.
Bien escritos los scripts en Perl se asemejan bastante a PHP. La principal causa
de la sucía apariencia de Perl es por la afición de sus desarrolladores a la
escritura en "una línea" empaquetanto numerosas funcionalidades en una sola
línea de código.
¿Por qué deberías aprenderlo?
La potencía de Perl a la hora de procesar grandes cantidades de datos lo hace
realmente popular a la hora de desarrollar aplicaciones del lado del servidor,
aprender Perl o Php es básico a la hora de desarrollar aplicaciones Web.

3.9.6.C
Es un lenguaje de "medio nivel" pero con numerosas características de bajo
nivel. Dispone de las estructuras típicas de los lenguajes de alto nivel pero, a
su vez, dispone de construcciones del lenguaje que permiten un control a muy
bajo nivel.
¿Por qué deberías aprenderlo?
Aprender C es básico mientras aprendes C estas aprendiendo conceptos
básicos de lenguajes cómo Java o C#, además no sólo es mas sencillo que
estos últimos sino que comporten gran parte de su sintaxis.

3.9.7.RUBY Y RUBY ON RAILS


Ruby on Rails, también conocido como RoR o Rails es un framework de
aplicaciones web de código abierto escrito en el lenguaje de programación
Ruby. Ruby apareció en el año 1995 y creo que su principal problema había
sido la falta de documentación en otro idioma que no sea japonés. Eso se ha
ido solucionando y crece la popularidad del lenguaje. Su aplicación insignia,
por decirlo de algún modo parece ser RoR. Su mecanismo de gem parece al
CPAN de Perl y al Pear de PHP
¿Por qué deberías aprenderlo?
Simple y funcional, el uso de Active Record de forma eficiente simplifica y
agiliza el desarrollo de forma notable. Al minimizar el trabajo con la base de
datos (escribiendo triggers y procedimientos almacenados) y emplear un único
lenguaje para todo el desarrollo, se consigue acortar los tiempos de desarrollo
(time2market).

3.9.8.ASP
Active Server Pages (ASP) y ASP.NET es un intento de Microsoft para
introducirse en el mercado del desarrollo Web, y viene a ser como su estandar
para su servidor Web, IIS. ASP ha sido atacado por la comunidad open source
desde que este apareció, y dan numerosas razones para ello:
El propietario, una única plataforma, la lentitud...
ASP ha sido implementado en otras plataformas y que cuando esta
funcionando bajo su servidor predeterminado IIS es relativamente rápido.
¿Por qué deberías aprenderlo?
Simplemente porqué en algunas ocasiones no tienes otra opción debido a la
popularidad que ha alcanzado.
CAPÍTULO IV: LENGUAJES DE BAJO, MEDIO Y ALTO
NIVEL

4.1. INTRODUCCIÓN

El ordenador sólo entiende un lenguaje conocido como código binario o código


máquina, consistente en ceros y unos. Es decir, sólo utiliza 0 y 1 para codificar
cualquier acción.
Los lenguajes más próximos a la arquitectura hardware se denominan lenguajes de
bajo nivel y los que se encuentran más cercanos a los programadores y usuarios se
denominan lenguajes de alto nivel.

4.2. LENGUAJES DE BAJO NIVEL

Vistos a muy bajo nivel, los microprocesadores procesan exclusivamente señales


electrónicas binarias. Dar una instrucción a un microprocesador supone en
realidad enviar series de unos y ceros espaciadas en el tiempo de una forma
determinada. Esta secuencia de señales se denomina código máquina. El código
representa normalmente datos y números e instrucciones para manipularlos. Un
modo más fácil de comprender el código máquina es dando a cada instrucción un
mnemónico, como por ejemplo STORE, ADD o JUMP. Esta abstracción da como
resultado el ensamblador, un lenguaje de muy bajo nivel que es específico de cada
microprocesador.
Los lenguajes de bajo nivel permiten crear programas muy rápidos, pero que son a
menudo difíciles de aprender. Más importante es el hecho de que los programas
escritos en un bajo nivel son totalmente dependientes de la máquina o de cada
procesador. Si se lleva el programa a otra máquina se debe reescribir el programa
desde el principio. Al estar prácticamente diseñados a medida del hardware,
aprovechan al máximo las características del mismo.
Dentro de este grupo se encuentran:
 LENGUAJE MÁQUINA.
 ENSAMBLADOR.
4.2.1.LENGUAJE MÁQUINA.
El lenguaje máquina es el único lenguaje que entiende directamente la
computadora. Por esta razón, su estructura esta totalmente adaptada a los
circuitos de la máquina y muy alejado de la forma de expresión y análisis de
los problemas propia de los humanos. Esto hace que la programación en este
lenguaje resulte tediosa y complicada, requiriéndose un conocimiento
profundo de la arquitectura física del ordenador. Frente a esto, el código
máquina hace posible que el programador utilice la totalidad de los recursos
que ofrece el ordenador, obteniéndose programas muy eficientes (es decir,
que aprovechan al máximo los recursos existentes) en tiempo de ejecución y
en ocupación de memoria.

4.2.2.ENSAMBLADOR.
El lenguaje ensamblador constituye el primer intento de sustitución del
lenguaje máquina por uno más cercano al usado por los humanos. Este
acercamiento a las personas se plasma en las siguientes aportaciones:
 Uso de una notación simbólica o nemotécnica para representar los
códigos de operación
 direccionamiento simbólico
 Se permite el uso de comentarios entre las líneas de instrucciones,
haciendo posible la redacción de programas más legibles.

Aparte de esto él LE presenta la mayoría de los inconvenientes del lenguaje


máquina, como son su repertorio muy reducido de instrucciones, el rígido
formato de instrucciones, la baja potabilidad y la fuerte dependencia del
hardware. Por otro lado mantiene la ventaja del uso óptimo de los recursos
hardware, permitiendo la obtención de un código muy eficiente.
Ese tipo de lenguajes hacen corresponder a cada instrucción en ensamblador
una instrucción en código máquina. Esta transducción es llevada a cabo por
un programa traductor denominado Ensamblador.
Para solventar en cierta medida la limitación que supone poseer un repertorio
de instrucciones, tan reducido, se han desarrollado unos ensambladores
especiales denominados macroensambladores.
Los lenguajes que traducen los macroensambladores disponen de
macroinstrucciones cuya traducción da lugar a varias instrucciones máquina
y no a una sola.
Dado que el lenguaje ensamblador esta fuertemente condicionado por la
arquitectura del ordenador que soporta, los programadores no suelen escribir
programas de tamaño considerable en ensamblador. Mas bien usan este
lenguaje para afinar partes importantes de programas escritos en lenguajes
de más alto nivel.
Hay un distinto Lenguaje de Máquina (y, por consiguiente, un distinto
Lenguaje Ensamblador) para cada CPU. Por ejemplo, podemos mencionar
tres lenguajes completamente diferentes, que sin embargo vienen de la
aplicación de los conceptos anteriores:
 Lenguaje Ensamblador de la familia Intel 80x86
 Lenguaje Ensamblador de la familia Motorola 68000
 Lenguaje Ensamblador del procesador POWER, usado en las IBM
RS/6000.

Tenemos 3 fabricantes distintos, compitiendo entre sí y cada uno aplicando


conceptos distintos en la manufactura de sus procesadores, su arquitectura y
programación; todos estos aspectos, influyen en que el lenguaje de máquina
y ensamblador cambie bastante.

A) VENTAJAS DEL LENGUAJE ENSAMBLADOR


Una vez que hemos visto la evolución de los lenguajes, cabe preguntarse:
¿En estos tiempos "modernos", para qué quiero el Lenguaje
Ensamblador?
El proceso de evolución trajo consigo algunas desventajas, que ahora
veremos como las ventajas de usar el Lenguaje Ensamblador, respecto a
un lenguaje de alto nivel:

1. Velocidad
El proceso de traducción que realizan los intérpretes, implica un
proceso de cómputo adicional al que el programador quiere realizar.
Por ello, nos encontraremos con que un intérprete es siempre más
lento que realizar la misma acción en Lenguaje Ensamblador,
simplemente porque tiene el costo adicional de estar traduciendo el
programa, cada vez que lo ejecutamos.
De ahí nacieron los compiladores, que son mucho más rápidos que
los intérpretes, pues hacen la traducción una vez y dejan el código
objeto, que ya es Lenguaje de Máquina, y se puede ejecutar muy
rápidamente. Aunque el proceso de traducción es más complejo y
costoso que el de ensamblar un programa, normalmente podemos
despreciarlo, contra las ventajas de codificar el programa más
rápidamente.
Sin embargo, la mayor parte de las veces, el código generado por un
compilador es menos eficiente que el código equivalente que un
programador escribiría. La razón es que el compilador no tiene tanta
inteligencia, y requiere ser capaz de crear código genérico, que sirva
tanto para un programa como para otro; en cambio, un programador
humano puede aprovechar las características específicas del
problema, reduciendo la generalidad pero al mismo tiempo, no
desperdicia ninguna instrucción, no hace ningún proceso que no sea
necesario.
Para darnos una idea, en una PC, y suponiendo que todos son buenos
programadores, un programa para ordenar una lista tardará cerca de
20 veces más en Visual Basic (un intérprete), y 2 veces más en C (un
compilador), que el equivalente en Ensamblador.
Por ello, cuando es crítica la velocidad del programa, Ensamblador se
vuelve un candidato lógico como lenguaje.
Ahora bien, esto no es un absoluto; un programa bien hecho en C
puede ser muchas veces más rápido que un programa mal hecho en
Ensamblador; sigue siendo sumamente importante la elección
apropiada de algoritmos y estructuras de datos. Por ello, se
recomienda buscar optimizar primero estos aspectos, en el lenguaje
que se desee, y solamente usar Ensamblador cuando se requiere más
optimización y no se puede lograr por estos medios.
2. Eficiencia de tamaño
Por las mismas razones que vimos en el aspecto de velocidad, los
compiladores e intérpretes generan más código máquina del
necesario; por ello, el programa ejecutable crece. Así, cuando es
importante reducir el tamaño del ejecutable, mejorando el uso de la
memoria y teniendo también beneficios en velocidad, puede convenir
usar el lenguaje Ensamblador. Entre los programas que es crítico el
uso mínimo de memoria, tenemos a los virus y manejadores de
dispositivos (drivers). Muchos de ellos, por supuesto, están escritos
en lenguaje Ensamblador.

3. Flexibilidad
Las razones anteriores son cuestión de grado: podemos hacer las
cosas en otro lenguaje, pero queremos hacerlas más eficientemente.
Pero todos los lenguajes de alto nivel tienen limitantes en el control;
al hacer abstracciones, limitan su propia capacidad. Es decir, existen
tareas que la máquina puede hacer, pero que un lenguaje de alto nivel
no permite. Por ejemplo, en Visual Basic no es posible cambiar la
resolución del monitor a medio programa; es una limitante, impuesta
por la abstracción del GUI Windows. En cambio, en ensamblador es
sumamente sencillo, pues tenemos el acceso directo al hardware del
monitor.
Resumiendo, la flexibilidad consiste en reconocer el hecho de que
Todo lo que puede hacerse con una máquina, puede hacerse en el
lenguaje ensamblador de esta máquina; los lenguajes de alto nivel
tienen en una u otra forma limitante para explotar al máximo los
recursos de la máquina.
B) DESVENTAJAS DEL LENGUAJE ENSAMBLADOR
Por otro lado, al ser un lenguaje más primitivo, el Ensamblador tiene
ciertas desventajas respecto a los lenguajes de alto nivel:

1. Tiempo de programación.
Al ser de bajo nivel, el Lenguaje Ensamblador requiere más
instrucciones para realizar el mismo proceso, en comparación con un
lenguaje de alto nivel. Por otro lado, requiere de más cuidado por
parte del programador, pues es propenso a que los errores de lógica
se reflejen más fuertemente en la ejecución.
Por todo esto, es más lento el desarrollo de programas comparables
en Lenguaje Ensamblador que en un lenguaje de alto nivel, pues el
programador goza de una menor abstracción.

2. Programas fuente grandes


Por las mismas razones que aumenta el tiempo, crecen los programas
fuentes; simplemente, requerimos más instrucciones primitivas para
describir procesos equivalentes. Esto es una desventaja porque
dificulta el mantenimiento de los programas, y nuevamente reduce la
productividad de los programadores.

3. Peligro de afectar recursos inesperadamente


Tenemos la ventaja de que todo lo que se puede hacer en la máquina,
se puede hacer con el Lenguaje Ensamblador (flexibilidad). El
problema es que todo error que podamos cometer, o todo riesgo que
podamos tener, podemos tenerlo también en este Lenguaje. Dicho de
otra forma, tener mucho poder es útil pero también es peligroso.
En la vida práctica, afortunadamente no ocurre mucho; sin embargo,
al programar en este lenguaje verán que es mucho más común que la
máquina se "cuelgue", "bloquee" o "se le vaya el avión"; y que se
reinicialize. ¿Por qué?, porque con este lenguaje es perfectamente
posible (y sencillo) realizar secuencias de instrucciones inválidas,
que normalmente no aparecen al usar un lenguaje de alto nivel.
En ciertos casos extremos, puede llegarse a sobreescribir información
del CMOS de la máquina (no he visto efectos más riesgosos); pero, si
no la conservamos, esto puede causar que dejemos de "ver" el disco
duro, junto con toda su información.

4. Falta de portabilidad
Como ya se mencionó, existe un lenguaje ensamblador para cada
máquina; por ello, evidentemente no es una selección apropiada de
lenguaje cuando deseamos codificar en una máquina y luego llevar
los programas a otros sistemas operativos o modelos de
computadoras. Si bien esto es un problema general a todos los
lenguajes, es mucho más notorio en ensamblador: yo puedo reutilizar
un 90% o más del código que desarrollo en "C", en una PC, al
llevarlo a una RS/6000 con UNIX, y lo mismo si después lo llevo a
una Macintosh, siempre y cuando esté bien hecho y siga los
estándares de "C", y los principios de la programación estructurada.
En cambio, si escribimos el programa en Ensamblador de la PC, por
bien que lo desarrollemos y muchos estándares que sigamos,
tendremos prácticamente que reescribir el 100 % del código al
llevarlo a UNIX, y otra vez lo mismo al llevarlo a MAC.

4.3. LENGUAJES DE MEDIO NIVEL

Un lenguaje intermedio se puede definir como una manera de representar


procedimientos y estructuras de datos que sirva como entrada para una MV
(Maquina Virtual) 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.
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í:

Compilación
No hay que repetir la conversión de la misma
1.
Ventajas instrucción a código maquina cada vez que aparece
2. Los programas corren muy rápido
1. Perdida de claridad e información sobre el programa
Desventajas
2. Dificultad en localizar la fuente exacta de error
Ejemplo  ADA, C , C++, FORTRAN, Pascal

Interpretación
No hay pérdida de claridad ni de información sobre
1.
un programa ni sobre donde están los errores.
Ventajas
No hay que decodificar código que no se va a
2.
ejecutar
Los programas corren mucho mas lento – se paga el
Desventajas 1.
coste de decodificar cada instrucción
Ejemplo  HTML, Lisp , ML, Perl, Postscrip, Smalltalk

Estos dos casos representan los dos extremos porque 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.
Como se puede ver en los cuadros superiores, 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.
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.

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.

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).
4.4. LENGUAJES DE ALTO NIVEL

El avance en el desarrollo de "compiladores" e "intérpretes" (los dos tipos de


programas traductores) ha sido por lo tanto fundamental en el desarrollo de los
lenguajes de "3º generación" cuyas ventajas además de la facilidad de aprendizaje
y lectura/escritura son las facilidades de corrección, transformación y conversión
de un lenguaje a otro.
Los lenguajes de alto nivel tienen normalmente las características de
“Transportabilidad”. Es decir, están implementadas sobre varias maquinas de
forma que un programa puede ser fácilmente “Transportado” (Transferido) de una
maquina a otra sin una revisión sustancial. En ese sentido se llama
"Independientes de la maquina".
Los lenguajes de “Alto Nivel” son los más utilizados como lenguaje de
programación. Aunque no son fundamentalmente declarativos, estos lenguajes
permiten que los algoritmos se expresen en un nivel y estilo de escritura
fácilmente legible y comprensible por otros programadores.
Los lenguajes de alto nivel son normalmente fáciles de aprender porque están
formados por elementos de lenguajes naturales, como el inglés. En BASIC, el
lenguaje de alto nivel más conocido, los comandos como "IF CONTADOR = 10
THEN STOP" pueden utilizarse para pedir a la computadora que pare si
CONTADOR es igual a 10.
Están dirigidos a solucionar problemas mediante el uso de EDD's (Estructuras
Dinámicas de Datos: Son estructuras que pueden cambiar de tamaño durante la
ejecución del programa. Nos permiten crear estructuras de datos que se adapten a
las necesidades reales de un programa).
Estos lenguajes permiten al programador olvidarse por completo del
funcionamiento interno de la maquina/s para la que están diseñando el programa.
Tan solo necesitan un traductor que entiendan el código fuente como las
características de la maquina.
Suelen usar tipos de datos para la programación y hay lenguajes de propósito
general (cualquier tipo de aplicación) y de propósito especifico (como FORTRAN
para trabajos científicos).
Ejemplos de estos lenguajes de alto nivel son PASCAL, APL y FORTRAN (para
aplicaciones científicas), COBOL (para aplicaciones de procesamiento de datos),
SNOBOL (para aplicaciones de procesamiento de textos), LISP y PROLOG (para
aplicaciones de inteligencia artificial), C y ADA (para aplicaciones de
programación de sistemas) y PL/I (para aplicaciones de propósitos generales) .

4.5. GENERADORES DE APLICACIONES ó 4º NIVEL

Posteriormente, usando estos lenguajes, se han redactado programas destinados a


facilitar un número variado de operaciones en campos de aplicación específicos
como simulación de fenómenos físicos, manipulación de datos estadísticos, etc.
Los más avanzados y flexibles de estos programas son las planillas electrónicas u
hojas de cálculo y los programas de administración de archivos o bases de datos
Dados que tales aplicaciones no "hacen nada" sin que el usuario defina ciertas
estructuras y ciertas operaciones, pueden ser consideradas como "generadores" de
aplicaciones, aunque este nombre se reserva habitualmente para niveles más
avanzados en que los usuarios pueden generar sistemas muy diferentes unos de
otros, con "herramientas" que se parecen a lenguajes de programación. Estas
herramientas conforman los lenguajes de cuarto nivel que son por esencia
"programas para crear programas" con una finalidad específica, como el "CASE"
destinado a facilitar el trabajo de los analistas de sistemas.
CAPÍTULO V: ELEMENTOS DE UN LENGUAJE DE
PROGRAMACIÓN

5.1. ELEMENTOS SINTÁCTICOS DE UN LENGUAJE

El estilo sintáctico general de un lenguaje está dado por la selección de diversos


elementos sintácticos básicos. Los más destacados son:

 Conjunto de caracteres: La elección del conjunto de caracteres es la primera


que se hace al proyectar una sintaxis de lenguaje. Se usan palabras de 8 bits
aunque cada vez más se consideran las representaciones de 16 bits (65.536
caracteres diferentes).

 Identificadores: La sintaxis básica para identificadores, una cadena de letras y


dígitos que comienzan con una letra, tiene amplia aceptación. Las
variaciones entre lenguajes se encuentra entre los signos de puntuación
admitidos (“.” , ”,” , ”-“, “_”...).

 Símbolos de operadores: Casi todos los lenguajes emplean los caracteres


especiales “+” y “-“ para representar las dos operaciones aritméticas
básicas. También adoptan alguna combinación y utilización de caracteres
especiales para ciertos operadores.

 Palabras clave y palabras reservadas: Una palabra clave es un identificador


que se usa como una parte fija de la sintaxis de un enunciado (ej. IF). El
análisis sintáctico durante la traducción se facilita usando palabras reservadas.
La adicción de una nueva palabra reservada al lenguaje significa que todo
programa antiguo que utilice ese identificador como nombre de variable (u
otro nombre) ya no es sintácticamente correcto.

 Palabras pregoneras: Son palabras opcionales que se insertan en los


enunciados para mejorar la legibilidad.
 Comentarios: Ayudan a documentar el programa.

 Espacios en blanco: Sus regla varían entre los lenguajes.

 Delimitadores y corchetes: Un delimitador es un elemento sintáctico que se


usa simplemente para señalar el principio o el final de alguna unidad
sintáctica, como un enunciado o expresión. Se pueden usar simplemente para
mejorar la legibilidad o simplificar el análisis sintáctico.

 Formatos de campos libres y fijos: Una sintaxis es de campo fijo si los


enunciados de programa se pueden escribir en cualquier parte de un renglón de
entrada sin que importe la posición sobre el renglón o las interrupciones entre
renglones. Una sintaxis de campo fijo utiliza la posición sobre un renglón de
entrada para transmitir información.

 Expresiones: Son los bloques sintácticos de construcción a partir de los cuales


se construyen enunciados (y a veces programas).

 Enunciados: Constituyen el componente sintáctico más destacado en los


lenguajes imperativos. Su sintaxis tiene un efecto decisivo sobre la
regularidad, legibilidad y facilidad de escritura generales del lenguajes.

5.2. TIPOS DE DATOS

Un tipo de datos es una clase de objetos de datos ligados a un conjunto de


operaciones para crearlos y manipularlos.
Todo lenguaje tiene un conjunto de tipos primitivos de datos que están
integrados el lenguaje. Además, un lenguaje puede proveer recursos que permitan
al programador definir nuevos tipos de datos.
Los elementos básicos de una especificación de un tipo de datos son:

A. Los atributos que distinguen objetos de datos de ese tipo.


B. Los valores que los objetos de datos de ese tipo puede tener, y
C. Las operaciones que definen las posibles manipulaciones de objetos de datos
de ese tipo.

Los elementos básicos de la implementación de un tipo de datos son:


A. La representación de almacenamiento.
B. La manera en que las operaciones definidas para el tipo de datos se representan
en términos de algoritmos o procedimientos particulares que manipulan la
representación de almacenamiento elegida para los objetos de datos.

5.3. NOTACIONES DE EXPRESIONES

El operador binario se aplica a los operandos. En notación infija, un operador


binario se coloca entre sus operandos, como en la expresión a + b. Otras opciones
son la notación prefija (polaca) , en la cual el operador aparece primero, como en
+ab , y la notación postfija (polaca inversa) en la cual el operador se escribe al
final, como en ab+.
Los paréntesis no son necesarios en notación prefija o postfija, debido a que los
operandos de cada operador pueden encontrarse sin peligro de ambigüedad.

Ejemplo: (X+Y)* Z
Notación Prefija: [ + XY ] * Z
* + XYZ

Notación Postfija: [ XY +] * Z
XY + Z *

5.4. PROPIEDAD ASOCIATIVA Y PRECEDENCIA

Convención Tradicional.

↑ Exponenciación
* , / Multiplicación, división
+ , - Suma, resta
5.5. REPRESENTACIÓN DE ÁRBOL PARA EXPRESIONES

Ejemplo. INFIJA : b * b - 4 * a * c
PREFIJA : - * b b * * 4 a c
POSTFIJA : b b * 4 a * c * -
Árbol de sintaxis abstracta

5.6. EVALUACIÓN DE EXPRESIONES

5.6.1.EVALUACIÓN MEDIANTE LA RECONSTRUCCIÓN DE UN ÁRBOL.

7*7- 4*2*3
5.6.2.EVALUACIÓN MEDIANTE UNA PILA

1. Traduzca a notación postfija la expresión que se evaluará.


2. Recorra la notación postfija de izquierda a derecha.
a) Al encontrar una constante introduzca su valor a la pila
b) Al encontrar un operador binario extraiga dos valores de la pila,
aplique el operador a esos valores e introduzca el resultado en la pila.

3. Después de recorrer toda la notación postfija, el valor de la expresión se


encuentra en el tope de la pila.

Ejemplo:
Expresión Pila auxiliar Comentario
77*42*3*- 7 Introduzca 7
7*42*3*- 77 Introduzca 7
*42*3*- 49 Multiplique
42*3*- 49 4 Introduzca 4
2*3*- 49 4 2 Introduzca 2
*3*- 49 8 Multiplique
3*- 49 8 3 Introduzca 3
*- 49 24 Multiplique
- 25 Reste

A) Algoritmo para transformar una notación infija a postfija.


Paréntesis :() Mayor prioridad
Potenciación : ↑
Multiplicación , División : * , /
Suma , Resta :+,-

Descripción Solución:
1. La expresión se va leyendo carácter a carácter, los operandos pasan
directamente a formar parte de la expresión en postfija.
2. Los operadores se meten en la pila siempre que esta este vacía o bien
siempre que tengan mayor prioridad que el operador cima de la pila (o
bien igual si es la máxima prioridad). Si la prioridad es menor o igual
se saca el elemento cima de la pila y se vuelve a hacer la comparación
con el elemento cima.
3. Los paréntesis izquierdos siempre se meten en la pila con la mínima
prioridad. Cuando se lee un paréntesis derecho, hay que sacar todos los
operadores de la pila pasando a formar parte de la expresión postfija,
hasta llegar a un paréntesis izquierdo, el cual se elimina, ya que los
paréntesis no forman parte de la expresión postfija.
4. El algoritmo termina cuando no hay más caracteres en la expresión y
la pila esta vacía.

Ejemplo:
A*(B+ C-(D/E ↑ F)-G )–H

caracter leído Expresión Estado de la pila


A A
* A *
( A *(
B AB *(
+ AB *(+
C ABC *(+
- ABC+ *(-
( AB C+ *(-(
D AB C+ D *(-(
/ AB C+ D *(-( /
E AB C+ D E *(-( /
↑ AB C+ D E *(-( / ↑
F AB C+ D E F *(-( / ↑
) AB C+ D E F↑/ *(-
- AB C+ D E F↑/- *(-
G AB C+ D E F↑/- G *(-
) AB C+ D E F↑/- G- *
- AB C+ D E F↑/- G- * -
H AB C+ D E F↑/- G- *H -
AB C+ D E F↑/- G- * H -

En la descripción realizada, se observa que el paréntesis izquierdo tiene la


máxima prioridad fuera de la pila, es decir, en la notación infija; sin embargo,
cuando esta dentro de la pila la prioridad es mínima.
De igual forma, para tratar el hecho de que varios operadores de
potenciación son evaluados de izquierda a derecha, este operador tendrá mayor
prioridad cuando no esta metido en la pila que el mismo pero metido en la pila.
B) Tabla de prioridades.

Operador Prioridad dentro de la pila Prioridad fuera


de la pila
↑ 3 4
* , / 2 2
+ ,- 1 1
( 0 5

C) Algoritmo (pseudocódigo)
1. Obtener caracteres de la expresión y repetir pasos 2 al 4 para cada
carácter
2. Si es operando, pasarlo a la expresión postfija
3. Si es operador
3.1. Si la pila esta vacía meterlo en la pila. Repetir a partir de 1.
3.2. Si la pila no esta vacía.
Si la prioridad del operador leído es mayor que la prioridad del
operador cima de la pila, meterlo en la pila
y repetir a partir de 1.
Si la prioridad del operador es menor o igual que la prioridad del
operador de la cima, sacar de la cima y
pasarlo a la expresión postfija, volver a 3.
4. Si es paréntesis derecho
4.1. Sacar cima de la pila y pasarlo a la expresión postfija
4.2. Si nueva cima es paréntesis izquierdo, suprimir elemento cima.
4.3. Si cima no es paréntesis izquierdo, volver a 4.1
4.4. Volver a partir de 1.
5. Si quedan elementos en la pila, pasarlos a la expresión postfija
6. Fin del algoritmo.

You might also like