Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la...

38
CENTRO POLITÉCNICO SUPERIOR Lenguajes de programación: Motivación 3º Ingeniería Informática Francisco José Serón Arbeloa Juan Antonio Magallón Sandra Baldassarri DEPARTAMENTO DE INFORMÁTICA E INGENIERÍA DE SISTEMAS UNIVERSIDAD DE ZARAGOZA

Transcript of Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la...

Page 1: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

CENTRO POLITÉCNICOSUPERIOR

es de programación: Motivaciónº Ingeniería Informática

Francisco José Serón ArbeloaJuan Antonio Magallón

Sandra Baldassarri

DEPAINF

INGENIEUNIVERSIDAD DE

ZARAGOZA

Lenguaj3

RTAMENTO DEORMÁTICA ERÍA DE SISTEMAS

Page 2: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas
Page 3: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

"Lenguajes de Programación"

INTRODUCCIÓN

Page 4: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas
Page 5: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

INTRODUCCIÓN

El propósito de un lenguaje es sencillamente el de transferir significado.Confucio

Los lenguajes de programación son el corazón de laInformática, ya que son las herramientas que se usanpara comunicarse no sólo con el computador sino conla gente.

El desafío que representa el diseño de un lenguaje esel de “juntar de manera adecuada” diferentes ideas ycaracterísticas, que permitan al programador laexpresión clara de los algoritmos.

Este conjunto de notas de clase sobre los lenguajes deprogramación, presentan los conceptos que subyacenen los lenguajes de programación y la mayor parte delos paradigmas que usan estos conceptos en formadiferente.

Las notas de clase se han agrupado en cuatrobloques. En este primer bloque se transcribe de formaíntegra la conferencia impartida por el profesorRicardo Peña Marí, en la Universidad de Zaragoza, el19 de Marzo de 1996 durante el ciclo de conferenciasJetai’96.

Page 6: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

Consideramos este documento de interés suficientecomo para motivar al alumnado en el estudio de losdiferentes aspectos relacionados con los Lenguajes deProgramación.

Los autores

Page 7: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

"Lenguajes de Programación"

EVOLUCIÓN HISTÓRICA DE LAPROGRAMACIÓN DE COMPUTADORES

Page 8: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas
Page 9: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

EVOLUCIÓN HISTÓRICADE LA PROGRAMACIÓN DE

COMPUTADORES.

Ricardo Peña Marí

Univ. Complutense de Madrid

Page 10: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas
Page 11: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

1

Evolución histórica de la programación de computadores

Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas Informáticos

Departamento de Informática y Automática Universidad Complutense de Madrid

e-mail: [email protected] de 1996

En este trabajo se realiza un recorrido por loshitos más relevantes de la historia de laprogramación de computadores. Se trata,obviamente, de una visión subjetiva -e inclusopersonal- de la misma. Se han omitido hechosque para otras personas pueden resultarimportantes y se han resaltado otros que quizása algunos no les parezcan merecedores de talrelieve. Comenzando por los hechos más lejanosen el tiempo se dedica después una sección areferir el surgimiento y la evolución posterior decada uno de los cinco paradigmas principales dela programación: el imperativo, el orientado aobjetos, el concurrente, el lógico y el funcional. Hasta donde llega el conocimiento del autor, sehan tratado de señalar las principales líneas deinvestigación y el estado actual de cadaparadigma.

1 Los tiempos remotos

La programación se ocupa de resolverproblemas algorítmicos. Un algoritmol se puededefinir como un conjunto de reglas precisas, queaplicadas sistemáticamente a partir de los datosiniciales, producen, en un número finito depasos, el resultado deseado. Las reglas han deser tan precisas y elementales que puedan seraplicadas por una máquina. Es ya un tópico afirmar que los algoritmospreceden históricamente a los computadores. Laregla de Cramer para el cálculo de undeterminante o método de reducción de Gausspara resolver sistemas lineales de ecuacionesson ejemplos de algoritmos, y fueron inventadosrespectivamente en los siglos XVIII y XIX. Losprimeros algoritmos conocidos proceden de laantigua Mesopotamia, datan aproximadamentedel 3.000 A.C., y estaban escritos en tablillas dearcilla. Su propósito era la realización decálculos----------------------------------------------------------

1 Palabra formada a partir del nombre delmatemático árabe del siglo IX Mohammed ibnMusa Abu Djefar Al-Khwarizmi.

tan pragmáticos como el del capital resultantede un préstamo a interés compuesto y otrossimilares. Terminaban con la siguienteinscripción premonitoria:

". . . y éste es el procedimiento. "

Los egipcios, griegos y romanos enriquecieronnotablemente la colección de algoritmos con susavances en geometría y aritmética. Uno de losmás famosos es el algoritmo de Euclides (300A.C.) para el cálculo del máximo comúndivisor. Pero el sueño del hombre ha sido siempre idearmáquinas que trabajasen para él, y los procesosmentales de cálculo -muchas veces tediosos ysujetos a error humano- no podían ser laexcepción. La primera calculadora mecánicadata de 1641, y se debe a Blaise Pascal. Laconstruyó a la edad de 19 años para ayudar a supadre en la voluminosa contabilidad necesariapara la recaudación de impuestos. La máquinade Pascal sólo era capaz de sumar y restar. La primera máquina realmente programable fuela Analythical Engine de Charles Babbage,construída en 1833. Era totalmente mecánica ytenía unidades semejantes a las de uncomputador actual: una unidad aritmética -themill-, una memoria formada por ¡50.000! ruedasdentadas, y unos mecanismos de transmisiónpara bombear datos y resultados entre ambasunidades. Aunque nunca llegó a funcionarcompletamente, tuvo un efecto importante parala programación (descontando el efecto lateral,importante sólo para su creador, consistente enllevarle a la ruina): la de obligar a plantearse porvez primera la necesidad de describir algoritmospara ser ejecutados por una máquina. Habíanacido la programación. El "software" de la citada máquina consistía ensecuencias de tarjetas perforadas donde estabandescritos los algoritmos. Éstos usaban ya elconcepto de bucle, implementado mediante lalectura repetida de las mismas tarjetas. Laprogramadora de los mismos era Ada Augsusta,Condesa de Lovelace, e hija

Page 12: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

2

del poeta Lord Byron, que ha pasado a laposteridad como la primera programadora de lahistoria. El nombre Ada, dado a un lenguaje deprogramación de los 80 (ver la Sección 3), hacehonor a este hecho. Las siguientes máquinas programablescorresponden ya a los años 40 del presentesiglo. Sus vicisitudes no forman propiamenteparte de la historia de la programación sino másbien de la de los computadores. Laprogramación se realizaba, primero en len-guaje numérico, también llamado lenguajemáquina, y más adelante, en lenguaje simbólicoo ensamblador. A los programadores de esosaños se les llamaba codificadores, quizás paraindicar que las verdaderas protagonistas eran lasmáquinas y no los programas. En aquellos días,los programadores entraban respetuosamente enlos templos donde moraban las máquinas -laENIAC de 1946, ocupaba todo un edificio-pertrechados tan sólo de una pequeña cartulinaen la que se describía el lenguaje de "la divi-nidad". Irónicamente, la situación se hainvertido en la actualidad: hoy el computadorocupa un pequeño rincón de la mesa, mientrasque los manuales para utilizar los numerososprogramas que contiene llenan varios estantes. Hay, sin embargo, dos desarrollos matemáticos-todavía anteriores a la aparición de losprimeros computadores- que sí son relevantespara la historia de la programación: la máquinade Turing y el cálculo lambda. A comienzos de siglo, muchos matemáticospensaban que quizás todos los resultados de lasmatemáticas podrían obtenerse a partir de unreducido conjunto de axiomas y de reglas deinferencia. El problema consistía en dar condicho conjunto de axiomas. Si se lograba talempeño, todo teorema podría obtenerse demodo mecánico aplicando una secuencia finitade pasos de deducción. El teorema de incom-pletitud de K. Gödel, en 1931, deshizobruscamente tales esperanzas: cualquier sistemade axiomas lo suficientemente rico como paraincluir los números naturales y sus operacionesde suma y producto admitía fórmulas que nopodían ser demostradas ni refutadas empleandolas reglas de deducción del mismo. La siguiente pregunta obvia fue: ¿Cuáles son lossistemas de axiomas donde cabe esperar lapropiedad de demostración automática? Sedemostró que la pregunta era equivalente a estaotra: ¿Cómo se caracteriza el conjunto de lasfunciones efectivamente computables? Alan Turing propuso en 1936 [Tur36] talcaracterización por medio de la máquina quelleva su nombre. Se trata de una máquinaconceptual cuya evolución está gobernada por elcontenido de una memoria lineal de símbolospotencialmente infinita, una memoria finita deestados internos, y una función de transición

que determina los cambios de estado y las posi-bles alteraciones en el contenido de la memorialineal. Con este dispositivo, mostró que eraposible calcular muchas de las funcionesusuales de los naturales en los naturales. Quedótambién claro que existían numerosas funcionesno calculables por su máquina, entre ellas elfamoso problema de parada: no existe unamáquina que decida si otra máquina de Turingarbitraria se detendrá ante una entrada dada.Más adelante, se propusieron versionesespecializadas de las máquinas de Turing condiferentes "necesidades" de memoria y seestableció una jerarquía de máquinas condiferentes potencias de cálculo. Esta jerarquía secorrespondía -en el sentido de aceptar frasesválidas de los mismos- con las categorías delenguajes formales establecidas por el lingüistaNoam Chomsky en los años 50 [Cho56]. Lallamada tesis de Turing (más adelante, llamadade Church-Turing) consiste en afirmar que elconjunto de las funciones computables coincideexactamente con el de las funciones calculadaspor las máquinas de Turing.Obviamente, tal conjetura no puede ser probadasin una caracterización previa de las funcionescomputables, por lo que puede tomarse comouna definición de las mismas. En apoyo de queesta definición representa la intuición adecuadade computabilidad, está el hecho de que otrossistemas de cálculo desarrolladosindependientemente llegaron a nociones decomputabilidad que se demostraronequivalentes a la definida por Turing. Entreellos se encuentra la teoría de funcionesrecursivas y el cálculo lambda. Éste último fue desarrollado por A. Churchentre 1932 y 1941 [Chu41]. El objetivo deChurch era capturar el aspecto computacionalde las funciones. En vez de usar la definicióntradicional de las mismas como conjuntos depares dato-resultado, su interés se centraba en elproceso de transformación desde el dato departida hasta el resultado de llegada. En suversión más simple, el cálculo lambda consisteen una gramática de términos y en unas reglasde transformación entre términos.Intuitivamente, estos términos representanfunciones. Una característica importante de estecálculo es la posibilidad de que las funcionespuedan aplicarse a sí mismas. Gracias a ello, sepueden definir funciones recursivas sin usarexplícitamente la recursividad. Pese a estaspropiedades, no aparecen paradojas oinconsistencias. La tesis de Church (o deChurch-Turing) consiste en afirmar que lasfunciones computables son exactamenteaquellas que pueden ser definidas mediante elcálculo lambda. Turing probó en 1937 [Tur37]la equivalencia entre este cálculo y susmáquinas, mostrando que cada uno podíasimular al otro. Las máquinas de Turing han dado lugar a unarama de la informática teórica conocida comoTeoría

Page 13: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

3

de la Computabilidad. Por su parte, el cálculolambda constituye la base teórica del paradigmade programación funcional. Ambos desarrolloshan sido fundamentales para comprender mejorcuáles son los límites de lo que es realizablemediante un computador.

2 Los primeros lenguajes de alto nivel

FORTRAN

La verdadera historia de la programación, talcomo la concebimos hoy, comienza con eldesarrollo de los lenguajes de alto nivel. Elprimero que merece tal nombre es el lenguajeFORTRAN (acrónimo de FORmulaTRANslating system), desarrollado por JohnBackus y sus colaboradores en IBM entre 1954y 1957 [IBM57]. Es de resaltar que el ambiente predominante enaquella época era bastante contrario a estedesarrollo. Backus tuvo que luchar contra elescepticismo de sus colegas y la indiferencia delos grupos de usuarios de IBM, que estabanconvencidos del fracaso del proyecto. Losprogramadores del momento utilizaban lenguajeensamblador con muy pocas ayudas mecani-zadas, quizás debido a que los computadores seconcebían como calculadoras exclusivamentenuméricas y no como procesadores de símbolos.Fueron tareas realmente meritorias, primeroconcebir el lenguaje, y después desarrollar elcompilador. Ello llevó tres años al equipo deBackus el cual, en ciertos momentos, llegó aalcanzar una docena de personas. También esmeritoria la apuesta de IBM por tal desarrollo.Backus convenció a sus superiores de que elnuevo lenguaje ahorraría mucho esfuerzo deprogramación. En esa época tan temprana, ya secomenzaba a intuir que los costes deprogramación terminarían por serpredominantes. El objetivo principal de Backusera reducir estos costes, pero era consciente deque el nuevo lenguaje no debería de sersignificativamente más lento que la codificaciónmanual porque entonces los programadores lorechazarían. La historia dio la razón a Backus y a la apuestade IBM. De hecho, Fortran contribuyó en granmanera al éxito de IBM que llegaría más tarde aser la compañía lider en ventas decomputadores. Fortran se convirtió en ellenguaje estándar para la programaciónnumérica y se desarrollaron compiladores paratodas las máquinas existentes. De la versión I,se pasó enseguida a la II, la III y la IV. Loscompiladores de esta última estuvierondisponibles en 1962. No obstante, lapreocupación por la eficiencia ha dejado suimpronta en el lenguaje, que hoy es a todasluces

obsoleto. Pero el hecho de ser el primer lenguajede alto nivel y haber sido promocionado por laprimera compañía mundial de computadores,ocasionó que se realizaran ingentes inversionesen desarrollo de software en dicho lenguaje,haciendo la pervivencia del mismo mucho máslarga de lo deseable, e impidiendo que lenguajesmás modernos tomaran el relevo. Las principales aportaciones de Fortran puedenresumirse como sigue:

. Lenguaje algebraico con notación muy cercanaa la matemática para las expresiones.

. Aritmética entera y de coma flotante.

. Estructura de datos array con variasdimensiones y con notación matemática.

. Subrutinas y procedimientos. Si bien éste eraun concepto conocido, la sintaxis escogida enFortran para su llamada con parámetros era muyintuitiva.

. Instrucciones declarativas COMMON yEQUIVALENCE para compartir y estructurarzonas de datos.

. Instrucciones de iteración y ramificación sincontrapartida inmediata en lenguaje máquina:DO, IF aritmético, IF calculado.

. Entrada/salida con formato. Esta facilidadliberaba al programador de una de las tareasmás tediosas y más dependientes de la máquina.

Pero la aportación principal es, como se hadicho, la de ser un lenguaje de alto nivel, esdecir, la de permitir programar en una notaciónindependiente de la máquina. Esto tuvo laconsecuencia inmediata de incorporar al campode la programación a multitud de personas queno eran especialistas en un computadorconcreto, ni deseaban involucrarse en losdetalles internos de una máquina particular.

ALGOL 60 El éxito de Fortran abrió el camino al desarrollode nuevos lenguajes, y apenas empezada suandadura, los grupos de usuarios de distintascasas fabricantes -IBM incluida- instaron a lajoven Association for Computer Machinery(ACM) a que promoviera la definición de unlenguaje de alto nivel independiente de losfabricantes que permitiera una programaciónportable entre máquinas. Ésta nombró un comitécon participación de la industria (IBM, RandCorporation, Westinghouse, ...), los institutos deinvestigación (Massachusetts Institute ofTechnology, en adelante MIT) y lasuniversidades, cuya primera reunión

Page 14: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

4

tuvo lugar en 1958. En paralelo, en Europa yahabía comenzado un movimiento en el mismosentido patrocinado por la Asociación Alemanade Matemáticas y Mecánica (GAMM). Elcomité europeo estaba presidido por Fritz L.Bauer y posteriormente se incorporó Peter Naur.En el norteamericano, figuraban el propio J.Backus (IBM), y John McCarthy (MIT),posteriormente creador del lenguaje LISP.Reunidos conjuntamente alumbraron unapropuesta que fue llamada ALGOL 58 (deALGOrithmic Language) que, tras variosrefinamientos, se convirtió en el lenguaje Algol60 [Nau60, Nau63]. Había muchas contradicciones entre el equipoeuropeo y el norteamericano. Los primerosponían el acento en la solidez y claridad dellenguaje, mientras que los segundos lo poníanmás en la flexibilidad de las construcciones. Loseuropeos querían un lenguaje utilizable a cortoplazo, mientras que los norteamericanos loveían más como un estándar a medio plazo quesirviera de referencia, pero que no les impidierautilizar los lenguajes en cuyo desarrollo estabaninvolucrados. A pesar de estos problemas, ellenguaje producido reunió de un modo simple yelegante la mayoría de los conocimientos delmomento y resultó de gran calidad. Marcó unhito en la historia de los lenguajes y suinfluencia en los lenguajes posteriores fue muysuperior a la de Fortran. Durante una largaépoca, el término Algol-like se empleó paracaracterizar la mayor parte de los lenguajes quese diseñaban. Algol 60 se convirtió en elvehículo preferido para la publicación dealgoritmos, gracias entre otras razones al apoyode ACM y de la revista Algol creada en Europapara su difusión. Sin embargo, no llegó adifundirse en la industria debido a que lascompañías fabricantes no pusieron especialempeño en el desarrollo de compiladores.Contemplaban Algol 60 como una notaciónelegante, pero ineficiente de implementar yprefirieron ocuparse de sus propios lenguajes.En particular, IBM estaba en esos momentosmuy interesada en promocionar Fortran. Son muchas las aportaciones de Algol 60,algunas de las cuales se dan hoy por supuestasen el desarrollo de cualquier lenguaje. Unejemplo de ello es la sintaxis BNF (Backus andNaur Form) desarrollada por dichos autorespara expresar su gramática. Esta notaciónsistemática dio lugar a un renovado interés porlos lenguajes formales, a muchas de las técnicasde análisis sintáctico que hoy conocemos, y a laconstrucción de generadores de analizadores, esdecir, de analizadores parametrizados por unagramática. Otras aportaciones no menosrelevantes de Algol 60 fueron las siguientes:

. Primer lenguaje con formato libre: los blancoso fines de linea adicionales al primero que

aparece no son significativos, y son eliminadosen la fase de análisis léxico. Introducción del símbolo ‘;’ yde las construcciones parentizadas begin endpara separar sintácticamente las instrucciones.

· Primer lenguaje con estructura de bloques.Introduce las reglas de visibilidad hoy tanhabituales: el ámbito de los identificadores eslocal al bloque en que están declarados. Sonvisibles los identificadores locales al bloque ylos de los bloques circundantes que nocolisionen con identificadores más internos enla jerarquía de anidamiento. Los bloquespermiten la declaración de variables temporalesen medio de un texto ejecutable: en cualquierpunto del texto puede iniciarse un nuevo bloquey declarar variables locales al mismo.

· Primer lenguaje con disciplina de tipos. A di-ferencia de Fortran, todas las variables han deser declaradas, junto con su tipo, antes de sernombradas. El compilador comprueba que cadavariable se usa de modo consistente con su tipo.

· Primer lenguaje con instruccionesestructuradas de control de flujo. En particular,las instrucciones for e if then else sonaportaciones de Algol 60.

· Primer lenguaje en introducir la recursividad,si bien los autores tuvieron muchas dudas antesde incluirla debido sobre todo a que no seconocía un modo eficiente de implementarla.

· Primer lenguaje en introducir los pasos deparámetros por valor y por nombre. Este últimoha sido abandonado en posteriores lenguajes im-perativos debido a sus complejos efectos latera-les.

· Límites de los arrays decididos en tiempo deejecución. Esto conlleva la asignación dinámicade memoria al dar comienzo a un bloque, y lasubsiguiente liberación de la misma alabandonar su ejecución.

COBOL El lenguaje COBOL, acrónimo de "COmmonBusiness Oriented Language", se gestó tambiéna finales de los 50, entre 1959 y 1961 [DoD60,DoD61]. Respondía a la necesidad de contarcon un lenguaje adaptado a la programación degestión, que se alejara de la aparienciaalgebraica de los lenguajes numéricos, y quepusiera el énfasis en los aspectos de descripciónde datos y de manipulación de ficheros. Su desarrollo contó con el apoyo financiero ypolítico del Departamento de DefensaNorteamericano (DoD) interesado en tener unlenguaje de dichas

Page 15: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

5

características. Estimulado por la industria, pusoen marcha el comité CODASYL2 que coordinólos trabajos. Participaban las empresas másimportantes (Sperry Rand, Burroughs, IBM,GE, Honeywell Bull, etc.), representantes delDoD y de las instituciones de estándares. Lapresencia de la universidad era meramentesimbólica. Persona importante en dicho comitéfue Grace M. Hopper (Sperry Rand) autora dellenguaje FLOW-MATIC -y de suscompiladores- en el cual Cobol se inspiróbastante. Una característica original de Cobol, sobre laque había unanimidad entre sus diseñadores yque sin embargo no ha tenido continuadores, esel uso de palabras inglesas para construir todaslas expresiones e instrucciones del lenguaje,incluidas las operaciones aritméticas (que enCobol reciben los nombres ADD,SUBSTRACT, etc.), dando a los programas unaspecto verboso muy peculiar. La razón de estadecisión de diseño era hacer los programascomprensibles a programadores y ejecutivos sinuna especial formación matemática. Es dudosoque tal objetivo se consiguiera. En cambio, noes dudoso que muchos programadores de Coboldeploran esta característica, y que se handesarrollado preprocesadores que permitentrabajar con una notación más abreviada. Más influencia posterior ha tenido su énfasis enindependizar la descripción de los datos de la delos procedimientos, y en hacer aquélla lo másindependiente posible del hardware subyacente.Así, un programa Cobol tiene cuatro apartados:

l. La identification division, que suministracomentarios explicativos acerca del programa ysus autores.

2. La environment division, que proporcionainformación dependiente de la máquina y, enparticular, define la correspondencia entre losficheros externos y las descripciones internas delos mismos.

3. La data division, que describe a nivel lógicola estructura de los ficheros utilizados por elprograma.

4. La procedure division, que describe losalgoritmos.

El sublenguage de descripción de datos puedeverse como la semilla cuyo fruto serían loslenguajes posteriores de descripción y consultade bases de datos. La estructura record estambién una aportación de Cobol a laposteridad. Cobol representó muy bien el consensoalcanzado por las empresas de la época paraconseguir un lenguage portable para susnecesidades de programación ----------------------------------------------------------2COmmittee on DAta SYstem Languages

de gestión. Se difundió rápidamente y fueconvertido en estándar ANSI en 1968, 1974 y1985. El énfasis en la portabilidad hizo queCODASYL se erigiera en vigilante de suevolución para evitar la proliferación deversiones incompatibles. Ello dio una gran esta-bilidad al lenguaje. Este hecho, junto con elapoyo decidido del DoD (ningún contrato con elmismo era aceptado si la compañía ofertante nodisponía de un compilador Cobol), hicieron que,como en el caso de Fortran, su pervivencia fueramás allá de los límites razonables. Todavía en ladécada de los 80, Cobol seguía siendo ellenguaje de programación más usado.

LISP

El origen de LISP (LISt Processing language) esmuy diferente. En este caso se trata del empeñode una persona, John McCarthy, del MIT, enconseguir un lenguaje apto para aplicaciones deinteligencia artificial. Al comenzarse lagestación de Lisp (1957) el único lenguaje dealto nivel era Fortran y ni siquiera estabafinalizado su compilador. Fortran erainadecuado para el tratamiento simbólico y parala creación de estructuras de datos dinámicas.Ello, junto a la ausencia de recursividad, queMcCarthy estimaba imprescindible, finalmentele decidieron a plantearse el desarrollo de unnuevo lenguaje. Un lenguaje previo, IPL,especie de macroensamblador interpretadodesarrollado por el Carnegie Institute ofTechnology, había demostrado la factibilidad deusar listas heterogéneas para representarcualquier información simbólica en la memoriadel computador. También habían implementadoun gestor de la memoria dinámica queproporcionaba celdas libres para la construcciónde tales estructuras de datos. Estas ideas fueronincorporadas a Lisp [MAE+62]. El primerintérprete estuvo disponible en 1960. Las aportaciones de Lisp son conceptualmentecomparables, aunque de distinto signo, a las deAlgol 60. La influencia posterior del lenguaje hasido profunda y el uso de sus dialectos -notoriamente, el del lenguaje Scheme, aparecidoen 1975 (ver p.e. [SF89])- ha pervivido hasta laactualidad. Estas aportaciones pueden resumirsecomo sigue:

. Demuestra en la práctica que la recursividad essuficiente para programar cualquier función.

. Trata las expresiones de datos y de programade modo uniforme. Las funciones se pueden pa-sar como parámetro y evaluarse posteriormente.Ello proporciona la primera notación de ordensuperior de la historia de los lenguajes.

. Esa misma facilidad permite evaluarprogramas completos dando lugar así a unintérprete. Lisp

Page 16: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

6

es también el primer lenguaje interpretado de lahistoria.

. También es pionero en la incorporación de unmecanismo automático de recolección debasura para reutilizar la memoria ocupada porexpresiones que ya no se van a necesitar.

. Utiliza la composición de funciones como me-canismo ordinario para la creación de funcionesmás complejas. También aporta una expresión -que no una instrucción- condicional. Ello haceque un subconjunto de Lisp sea un lenguajefuncional puro. Así, Lisp es una de las semillasque, tras una larga gestación (ver la Sección 7),da lugar a un nuevo paradigma deprogramación.

Se ha especulado mucho sobre la influencia delcálculo lambda en la gestación de Lisp. Elpropio McCarthy reconoce en [McC78] que esainfluencia fue pequeña, prácticamente limitada ala sintaxis empleada para las funcionesanónimas -la abstracción lambda λx.e se expresacomo (lambda(x)e) en Lisp. La utilización delcálculo lambda como fundamento semántico delos lenguajes funcionales vendría muchodespués.

La crisis

Un texto muy difundido en las empresas asegurairónicamente que las fases de un proyectoinformático son aproximadamente lassiguientes:

l. Comienzo del proyecto. Realización deestimaciones irreales.

2. Fase de optimismo desmesurado.

3. Fase de terror.

4. Fracaso del proyecto.

5. Búsqueda implacable de culpables.

6. Premio a estos últimos y castigo de losinocentes.

Si tuviéramos que aplicar este esquema aldesarrollo de los lenguajes de programación,diríamos que la década de los 60 correspondesin duda a la fase de "optimismo desmesurado".En estos años se desarrollan docenas delenguajes sin más justificación que la deexperimentar nuevas ideas. Ideas que surgíansin cesar en empresas y universidades. Quizás elentorno social (éxito sin precedentes de lamúsica pop, movimientos pacifistas, deliberación de la mujer, de contestación juvenil,etc.) era propicio al surgimiento de las mismas.Fue una época de gran creatividad. Algunos deestos lenguajes, como JOVIAL, Algol-W,BASIC, etc., eran de propósito general. Otroseran de propósito específico, como SNOBOL(tratamiento de

cadenas de caracteres), APL (procesamiento dematrices numéricas), GPSS (simulación) o losderivados de Lisp (tratamiento de símbolos). Sin embargo, no existían criterios claros paracomparar la bondad relativa de tales propuestas.La programación científica se había adherido aFortran, la empresarial a Cobol y cada áreaespecífica de aplicación disponía de su propiolenguaje. Empezó a tomar forma la idea de quesería deseable un lenguaje que sirviera "paratodo". Éste debería disponer de una buenanotación matemática para la expresión decálculos numéricos, de suficientes facilidadespara la descripción de datos, una entrada/salidaversátil y eficiente, y mecanismos para lacreación de estructuras dinámicas semejantes alas de Lisp. Adicionalmente, debería teneralgunas de las características de los lenguajesespecializados, tales como el tatamiento decadenas de caracteres o facilidades para lamultiprogramación, concepto surgido amediados de la década. Conviene enmarcar esta búsqueda de unlenguaje "más potente" en los avances enarquitectura de computadores que estabanteniendo lugar simultaneamente. Estamos en1965. Empiezan a surgir los primeros circuitosintegrados (tan solo unas docenas de transistorespor chip), las memorias de ferritas alcanzantamaños de 512 K-octetos y los tiempos de ciclose sitúan en torno a 1/4 de microsegundo. Haceunos años que se ha inventado la interrupciónpara des-sincronizar la UCP de los periféricos,cuatro órdenes de magnitud más lentos queaquella. Con ella ha surgido lamultiprogramación y todos los problemasderivados de la concurrencia. Se abordandesarrollos de decenas miles de instrucciones, eIBM está a punto de lanzar su serie 360. Estamos entrando -según el esquema delcomienzo de esta sección- en la "fase de terror".Algo no funciona en el mundo del software. Losdesarrollos no sólo conllevan un esfuerzodesmesurado, sino que los programasresultantes están plagados de errores. El propiosistema operativo de la serie 360 es un ejemplode ello: 5.000 personas-año costó su desarrolloy mantenimiento posterior, y el número deerrores detectados se mantenía estable de cadaversión a la siguiente. En este contexto, seaborda el diseño de dos nuevos lenguajes: PL/Iy Algol 68. El primero de ellos, en realidad contribuyó a la -más adelante- llamada "crisis del software". Supromotor fue IBM y su objetivo ser el lenguajebase para la serie 360. Esta familia estabadirigida tanto al mercado científico como alempresarial y, por tanto, el lenguaje deprogramación había de satisfacer a ambascomunidades. Su definición y desarrollo seextendieron desde 1964 a 1966 y en ellasparticiparon usuarios e implementadores deFortran y Cobol.

Page 17: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

7

El lenguaje resultante incluía características deambos, y algunas otras novedosas como elmanejo de excepciones o las primitivas del tipofork y join para lanzar procesos concurrentes.También suministraba punteros para la creaciónde estructuras de datos dinámicas.

El principal problema de PL/I era su volumen yla falta de ortogonalidad de sus caracteríticas.En realidad era una acumulación deconstrucciones de muy diverso tipo y suinteracción no estaba clara en muchos casos. Enpalabras posteriores de E. W. Dijkstra [Dij72a]"usar PL/I es como pilotar un avion con 7.000mandos distintos". Estas ambigüedades yvolumen retrasaron mucho la construcción delcompilador. Los diseñadores, conscientes deque sería difícil para un programador controlarsimultaneamente todos los rincones dellenguaje, tomaron una decisión de diseño que eltiempo demostró fue un error: la inclusión deopciones por defecto allí donde el pro-gramador no especificaba nada. Así, se podíanmezclar libremente variables de muy diversotipo en las expresiones sin que el compiladorseñalara esto como un error (aunque en algunoscasos pudiera ser simplemente una malatranscripción mecanográfica). El compiladortenía opciones por defecto para asignar un tipo ala expresión y para hacer las conversionesimplícitas oportunas, muchas veces para mayorsorpresa del programador. En ese sentido, PL/Irepresenta un paso atrás respecto a la disciplinade tipos de Algol 60.

PL/I no tuvo éxito entre sus potenciales usuariosa pesar de los esfuerzos de IBM por difundirlo.A petición de éstos, tuvo que desarrollar ysoportar compiladores de Fortran y Cobol parala serie 360. Quizás el único impacto positivo dePL/I en la historia de los lenguajes -aparte delconsabido consuelo de que "de los errorestambién se aprende"- fue el esfuerzo por definirformalmente su semántica. El laboratorio deIBM en Viena desarrolló el llamado ViennaDefinition Language, VDL [Weg72], lenguajeformal para expresar el significado de lasconstrucciones sintácticas de un lenguajemediante su interpretación en una máquinaabstracta. Este desarrollo dio lugar a toda unalínea de trabajo en semántica operacional queposteriormente evolucionó hacia la conocidacomo semántica denotacional [SS71]. Éste eshoy el modo estándar de definir la semántica delos lenguajes. De la complejidad de PL/I da ideael hecho de que su semántica formal necesitó400 páginas escritas en VDL [LW69]. Encontraste, la semántica formal de Algol 60 en elmismo lenguaje ocupa tan solo 50 páginas.

El segundo de los lenguajes de propósitogeneral desarrollado al final de la década, Algol68 [Wij69] ,

fue obra del grupo de trabajo WG 2.1 de laIFIP,3 y su principal objetivo de diseño era laortogonalidad. Algol 68 constaba de muy pocoselementos primitivos pero se podían combinarentre sí casi sin restricciones. Por ejemplo,disponía de cinco tipos básicos y de cincomodos distintos de formar tipos compuestos apartir de tipos más simples: arrays , structures(registros), uniones (equivalen a registros convariantes), punteros a elementos de un tipo m, yfunciones de un tipo m en un tipo n. Cualquiercombinación de estas construcciones eraaceptable. Así, Algol 68 buscaba la generalidadpor un camino distinto al de PL/I. Sin embargo,el lenguaje resultó bastante incomprensible ymuy dificil de implementar. Su impacto en laprogramación del momento fue mínimo. Con estos dos desarrollos, hemos alcanzado lafase de "fracaso del proyecto". Ahora se tratabade buscar a los culpables de tal situación.Quizás la aportación de Algol 68 a la historia delos lenguajes fue ésta: colaborar en la búsquedade los culpables. Algunos investigadores quehan marcado la década de los 70, tales comoC.A.R. Hoare y N. Wirth, se apartaron del WG2.1 ocupado en la definición de Algol 68 ycrearon un nuevo grupo, el WG 2.3, sobremetodología de la programación. Pensaron quese imponía un periodo de reflexión antes deabordar el diseño de nuevos lenguajes. Éstosdeberían reflejar una metodología para laconcepción de programas y no a la inversa. Peroesa metodología estaba por hacer. Su historia serelata en la siguiente sección.

3 La programación imperativa

El estilo de programación que se estababuscando tenía como objetivo que elprogramador fuera dueño de su herramienta, ellenguaje, y no al revés. Ello implicaba hacer usotan solo de construcciones que pudieran sercomprendidas perfectamente y que permitieranun razonamiento riguroso acerca de lacorrección de los programas con ellasconstruidas. Los primeros pasos en esadirección los dieron Hoare en [Hoa69] , Dijkstraen [Dij68c] y [Dij72b], y Wirth en [Wir71a]. El primero de ellos, con antecedentes en[McC62, Nau66, Flo67, Dij68a], establece losaxiomas fundamentales para la verificaciónmatemática de los programas. Por primera vezse disponía de un conjunto de leyes quepermitían razonar con todo el rigor deseadosobre la corrección de un programa escrito enun lenguaje de alto nivel. Más aún, esterazonamiento era independiente de cualquierimplementación del lenguaje y de cualquiercomputador en que se ejecutara el programa. Esdecir, los programas poseían un ----------------------------------------------------------

3International Federation for InformationProcessing

Page 18: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

8

significado por sí mismos, al margen de lasmáquinas que los ejecutaban. Estas leyes han deser consideradas de trascendental importancia.Al igual que la aritmética, la mecánica o elelectromagnetismo se apoyan en un conjuntoreducido de axiomas, por primera vez laprogramación disponía de un fundamentosimilar. El propio Hoare establece estacomparación en [Hoa84]. La verificación formal de programas sedesarrolla notablemente durante la década,impulsada sobre todo por E. W. Dijkstra. Sutrabajo [Dij75] y su libro posterior [Dij76] sontodavía hoy de obligada lectura. En ellos sepropone -y se ejercita mediante numerososejemplos nada triviales- la técnica de derivaciónformal, consistente en aplicar la verificación deun modo más cómodo y productivo que aposteriori, es decir, con el programa yaconstruido. Primero, el programador establecelos predicados que han de satisfacerse en ciertospuntos del programa, y muy particularmente losinvariantes de los bucles, y luego "deduce"sistemáticamente un programa que los satisface.De este modo, los programas resultantes soncorrectos por construcción. Adicionalmente, ellenguaje definido en [Dij75] introduce el nodeterminismo en la programación secuencial,concepto harto extraño para tan tempranomomento. Además de mejorar la presentaciónde algunos algoritmos secuenciales, lasconstrucciones no deterministas de [Dij75] vana tener una profunda influencia en los lenguajesconcurrentes del final de la década (ver laSección 5). Complementarios de las técnicas de verificaciónson el desarrollo de programas medianterefinamientos sucesivos [Wir71a, Dij72b] y eluso exclusivo de la composición secuencial, laalternativa if then else y la iteración while,como instrucciones para dirigir el flujo decontrol de un programa [Dij68c, Dij72b].Pueden utilizarse otras estructuras similares(p.e. repeat, case) siempre que tengan un sólopunto de entrada del control y un sólo punto desalida. El trabajo [BJ66] había dejadoestablecido que toda función computable podíaconstruirse con dichas estructuras. En definitiva,el go-to no era imprescincible, y en cambiocontribuía en gran manera a la oscuridad de losprogramas. Este conjunto de ideas(razonamiento formal, refinamientos yconstrucciones estructuradas) constituye elmensaje de la programación estructurada,movimiento cuyo nombre -al menos- llegó atodos los rincones del mundo de laprogramación a lo largo de dos décadas. Por elconjunto de sus aportaciones, que también seextienden al campo concurrente (ver Sección 5),Dijkstra recibió el premio Turing en 1972. En sudiscurso [Dij72a], aprovecha para arremetercontra los lenguajes de finales de los 60, muyespecialmente contra PL/I del que llega a decirque es como una "enfermedad mortal".

Estas reflexiones condujeron necesariamente adiseñar lenguajes mucho más modestos que losprecedentes, de forma que la simplicidad y laverificabilidad de las construcciones fueran elhilo conductor. La semántica axiomáticaproporcionaba así una herramienta objetiva paracomparar unos lenguajes con otros. En lamedida en que el conjunto de axiomas sevolviera inmanejable, el lenguaje dejaría de serútil. La programación con go-to era perjudicialno sólo porque resultaba subjetivamente másoscura, sino además porque hacía la tarea deverificación objetivamente más dificil, cuandono imposible. El lenguaje expresamente diseñado para reflejary enseñar las ideas de la programaciónestructurada, fue Pascal [Wir71b]. En aquelmomento, Niklaus Wirth era profesor en laUniversidad de Zurich y el único lenguajepráctico de que disponía para la enseñanza eraFortran. Wirth había sido uno de losinvestigadores disidentes del WG 2.1. Supropuesta para Algol68 había quedado enminoría y decidió implementarla con el nombrede Algol-W [Wir66]. Este lenguaje tuvo pocadifusión pero fue muy apreciado por los quetuvieron ocasión de usarlo. Tenía la mismasimplicidad de Algol 60, e incluía algunas cons-trucciones nuevas que fueron incorporadastambién a Pascal: registros, punteros,instrucción case, separación de for y while endos instrucciones y algunas otras. Pascal, por suparte, añade la posibilidad de que elprogramador defina y dé nombre a sus propiostipos, que pueden ser construidos a base decombinar, prácticamente sin restricciones, losconstructores array, record, file y set, los dosúltimos aportaciones originales de Pascal.También añade la definición de tiposenumerados y un concepto restringido desubtipo, los subrangos. Además de esta riquezasin precedentes en los tipos, otro de losobjetivos de Pascal era su implementacióneficiente, pues Wirth estimaba que sólo unlenguaje eficiente podría desplazar a Fortran.Por ello se decidió por unos arrays cuyo tamañohabía de fijarse en tiempo de compilación, loque suponía un paso atrás con respecto a Algol60. Wirth y sus colaboradores hicieron notablesesfuerzos por escribir un buen manual, al queañadieron una abundante colección de ejemplos[JW74], y por difundir sus técnicas decompilación, de forma que resultase fácil a otrosla construcción de compiladores. Pascal seconvirtió en poco tiempo en el lenguaje estándarpara la enseñanza de la programación en losprimeros cursos. Andando los años, y gracias aunas buenas implementaciones para loscomputadores medianos y pequeños, tambiénterminó por desplazar a Fortran en los ámbitosde la programación científica (excepto en lasaplicaciones de cálculo numérico y estadística).Así, Pascal es quizás el primer lenguaje

Page 19: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

9

que, sin gozar del soporte de una gran compañíao de una poderosa institución, ha obtenido laadhesión de una gran parte de la comunidadinformática. También fue el primer lenguaje quecontó con una definición axiomática de lapráctica totalidad de sus construcciones[HW73]. El segundo avance metodológico de la décadatiene que ver con la abstracción. Tanto Dijkstracomo Hoare ponen mucho énfasis en susescritos sobre esta herramienta mental de quedisponemos los humanos para disminuir elnúmero de detalles a tener en cuentasimultaneamente. De hecho, [Dij72b] comienzacon una sección titulada "Sobre nuestraincapacidad para hacer muchas cosas a la vez"en la que el autor se extiende sobre laslimitaciones de la mente humana y sobre eldesconocimiento de los programadores acercade este fenómeno. El deseo de una mayorabstracción subyace sin duda al surgimiento delos lenguajes de alto nivel y a la técnica deespecificación de procedimientos mediantepredicados. Pero la abstracción no había llegadoa las estructuras de datos. Tan temprano comoen 1972, Hoare tiene dos trabajos seminales,[Hoa72b] y [Hoa72a], en los que ya apunta lanecesidad de aplazar las decisiones derepresentación de la información lo más posiblecuando se diseñan programas grandes. Inclusoen [Hoa72b], introduce dos piezasfundamentales para el razonamiento sobrerepresentaciones de datos: el invariante de larepresentación y la función de abstracción. Pero es a partir de los trabajos de D. Parnas[Par72b, Par72a, Par74] y de B. Liskov [Lis72,Lis74] desde la parte industrial, y de J. Morris[Mor73] desde la parte universitaria, cuandosurge un nuevo concepto de profunda influenciaposterior en la programación: el de tipoabstracto de datos. La idea fundamental esconsiderar un tipo de datos como un conjunto devalores cuya representación en la memoria delcomputador es irrelevante -y por tanto no esnecesario conocerla para trabajar con él-, y a lavez como un conjunto de operaciones que sonlas únicas aplicables a los valores del tipo. La tesis de John Guttag [Gut75] acuña eltérmino y aporta numerosos ejemplos en los quese demuestra la utilidad del concepto. Además,introduce un técnica de especificaciónecuacional que formaliza el comportamientoobservable de un tipo abstracto (ver también[Lis75] y [GHM78b]). A efectos de progra-mación, la consecuencia inmediata es que untipo abstracto da lugar a un nuevo tipo demódulo donde la visibilidad de la representaciónse extiende a los procedimientos que componenel módulo, pero no a los procedimientosexternos al mismo. Los únicos identificadoresexportados por el módulo son el nombre del tipoy los nombres de sus operaciones. Las reglas devisibilidad de los lenguajes con estructura de

bloques no sirven a esta nueva necesidad y, portanto, aparece una nueva generación delenguajes que incorporan los mecanismos deocultamiento necesarios. Los primeros de ellosson CLU [LSAS77] y ALPHARD [WLS76] , yrápidamente les siguen otros. El propio Wirthdiseña, primero Modula [Wir77], y másadelante Modula-2 [Wir82] para adaptarse aesta necesidad. Además de estas aportaciones a la ingeniería dela programación, al suministrar un concepto demódulo, los tipos abstractos despiertan el interésde los investigadores teóricos. Un grupo deellos, proveniente de la teoría de categorías yempleados por el centro de investigaciónThomas J. Watson de IBM, se preocupan por elsignificado matemático de una especificaciónecuacional de un tipo abstracto. Deciden que elconcepto adecuado es el de álgebra heterogénea,y comprueban que la clase de álgebras quesatisfacen una especificación ecuacional, juntocon los homomorfismos entre ellas, constituyenuna categoría. Como anécdota, el grupo seautodenominó ADJ, a partir de los funtoresadjuntos (ADJunctions) que aparecen en lascategorías. Eligen como modelo representativode la especificación el modelo inicial que,intuitivamente, es el álgebra en la que sóloexisten valores generados por las operaciones yque satisface las ecuaciones dadas y ningunaotra adicional. Este modelo siempre existe y esúnico para una especificación dada. En adelante,las especificaciones ecuacionales de tiposabstractos se denominarían algebraicas. Laspublicaciones del grupo se extienden a lo largode toda la década [GTWW76, GTW78] yabrieron una linea de investigación que aúnpermanece viva. Las especificaciones sesofistican para poder expresar situaciones deerror, para tratar con operaciones parciales, opara poder construir modularmente grandesespecificaciones. Se diseñan lenguajes deespecificación y se construyen herramientaspara demostrar teoremas a partir de una espe-cificación. En muchos casos, una especificaciónes ejecutable, es decir, puede simular con todaprecisión el comportamiento del programa queespecifica. La técnica empleada para ambospropósitos (demostración de teoremas yejecución) es la de reescritura de términos[HO80, Les83, GH86]. Ello permite contem-plar los lenguajes de especificación comoverdaderos lenguajes de programación, de muyalto nivel, para la construcción de prototipostempranos en el desarrollo de software. Unlenguaje especialmente diseñado con estepropósito es OBJ2 [FGJM85]. Por otra parte, semantiene un vivo debate sobre si la semánticainicial es o no la más adecuada para unaespecificación algebraica. Se proponen otrassemánticas alternativas como la final, la laxa ola de comportamiento que quizás reflejan mejorla idea, asociada a los tipos abstractos,

Page 20: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

10

de ocultamiento de información. En [BW84] yen [Wir90] se da una amplia visión de estosaspectos semánticos. Una referencia obligadapara la semántica inicial es [EM85]. El concepto de tipo abstracto ha dado lugar aotras líneas de investigación. En el terreno deldesarrollo modular de grandes programas, sonimprescindibles las referencias [Lis79] y[LG86]. En ellas se propone un método dediseño a gran escala que puede verse como unapuesta al día, a la luz de los tipos abstractos, delmétodo de los refinamientos sucesivos de Wirth.Se presentan ejemplos de la magnitud suficientecomo para apreciar las dificultades y losbeneficios de la técnica. La forma de presentarlas estructuras de datos también cambianotablemente: ahora, se ha de distinguir entre eltipo observable, descrito por una especificación(por ejemplo, conjunto de pares (clave, valor),con operaciones de inserción, búsqueda,borrado, etc.), y las posibles representacionesusadas para el mismo (por ejemplo, tabla hash,árbol binario equilibrado, etc.). Algunos librosde texto (p.e. [AHU83, Mar86, HS90]) reflejanesta visión. Otro concepto importante es el deimplementación, es decir, el conjunto decriterios que aseguran que una representación, ysus procedimientos asociados, satisfacen elcomportamiento definido por una especificaciónalgebraica. Algunos trabajos clave son [Dah78,EKMP82, BMPW86, ONS92], pero se puededecir que, a efectos prácticos, el problemacontinúa abierto. Es decir, no parece haberseencontrado un modo de realizar estascomprobaciones con una inversión razonable deesfuerzo. Otros trabajos (p.e. [GHM78a,NHN78]) se han ocupado de combinar lastécnicas de verificación formal con predicados,con las de especificación ecuacional de tiposabstractos de datos. Finalmente, otra idea importante surgida al calorde esta investigación es la de genericidad. Untipo abstracto puede ser genérico oparametrizado en el sentido de que algunas desus características están indefinidas, o tan sóloparcialmente definidas. Al conjunto decaracterísticas indefinidas se le denominaparámetro formal. En una etapa posterior, seconcreta el tipo genérico suministrando unparámetro real en el que se precisan los detallesindefinidos. Proporcionando diferentesparámetros reales, se obtienen diferentes tiposconcretos. Esta idea, una vez incorporada a loslenguajes de programación, permite una graneconomía de esfuerzo. Por ejemplo, losalgoritmos de ordenación podrían tenersealmacenados en una librería de algoritmosgenéricos, y obtener la versión concreta deseadaindicando tan sólo el tipo de los elementos, eltamaño del vector a ordenar y la relación deorden a utilizar.

El lenguaje de programación que recoge lamayoría de estas aportaciones es Ada [Ada83].Se le dio este nombre en honor a Ada Augusta,Condesa de Lovelace y colaboradora de CharlesBabbage (ver la Sección 1). Su patrocinador,una vez más, fue el Departamento de Defensade los Estados Unidos, preocupado por losenormes costes de desarrollo de software quesoportaba. Sus responsables consideraron que, sidispusieran de un lenguaje con suficientesfacilidades para soportar la programación engran escala -es decir, modularidad, libreríasestándar, componentes reutilizables- y, enparticular, para la programación de sistemasempotrados4 -o sea, con construcciones para elmanejo de la concurrencia, de los dispositivosexternos y del tiempo real-, podrían prescindirde la mayoría de los lenguajes en uso en elDoD. Con ese fin, ponen en marcha uncomplejo mecanismo de creación deespecificaciones, evaluación de propuestas y desucesivos refinamientos, que culminan en ladefinición del mencionado lenguaje. Sus autoresson el grupo de Jean Ichbiah en Cii-HoneywellBull. El proceso se extiende en el tiempo desde1975 a 1980 [Ada79] y tiene oportunidad derecoger gran parte de las ideas reseñadas en lospárrafos precedentes, junto con otras sobreconcurrencia que se detallan en la Sección 5. Elprimer compilador certificado se termina en1983, año en que también es estandarizado ellenguaje por la ANSI [Ada83]. Por primera vez, un lenguaje se diseña a partirde unas especificaciones previas de requisitos.Las cuatro propuestas candidatas en la fase finalfueron sometidas a evaluación y crítica por partede numerosos grupos de potenciales usuarios.Es decir, se trata de un lenguaje hecho a lamedida de unas necesidades. Se admite el papelde Pascal como el principal lenguaje inspiradorde su diseño. El producto resultante es unlenguaje bastante voluminoso pero con unaunidad interna de la que carecían propuestasanteriores. No obstante, no se libró de la críticade Hoare, quien en la recepción del premioTuring [Hoa81] le acusó de excesivacomplejidad. Aunque actualmente está muydifundido, todavía es una incógnita su futuro. Elproceso de introducción ha sido más lento de lodeseable debido quizás al volumen eineficiencia -tanto en el proceso de compilacióncomo en el código generado- de los primeroscompiladores. Ada no pretendía innovar, sino más bien,utilizar conceptos ya probados. Por ejemplo,adopta una sintaxis parentizada, similar a la deModula-2, donde toda construcción tiene unapalabra clave que indica su final. Ello elimina elconocido problema del else pendiente enlenguajes como Algol 60, PL/I y Pascal. ----------------------------------------------------------

4En inglés, embedded systems, es decir,computadores que forman parte de un sistemahardware más amplio y al cual controlan.

Page 21: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

11

A pesar de lo dicho, pueden señalarse lassiguientes innovaciones de Ada con respecto alos lenguajes más cercanos:

. La construcción package, mecanismoprincipal de ocultamiento y de modularidad. Sedistingue entre su parte visible o interfaz consus usuarios, y su parte oculta, o body, cuyasdeclaraciones sólo son accesibles a losprocedimientos del package. Construcciónversátil que permite la definición de tiposabstractos, de objetos (ver Sección 4), decolecciones de procedimientos, o de zonasglobales de datos.

. Facilidades para la programación genérica.Tanto los packages como los procedimientos,pueden estar parametrizados por tipos,operaciones o constantes. El mecanismo deconcreción de una construcción genérica seconcibe como un macroexpansor que, trascomprobar la consistencia sintáctica entre elparámetro real y el formal, produce el códigoespecífico para esa concreción.

. Compilación separada como parte dellenguaje. Estos aspectos se dejabannormalmente abiertos en otros lenguajes. EnAda, el compilador se ocupa de mantener laconsistencia entre las interfaces de los módulosy sus respectivos bodies. Para compilar unmódulo usuario, sólo es necesario tenercompilada la parte de interfaz de los módulosutilizados. Ello facilita la realización de grandesprogramas, donde diferentes personas puedenestar trabajando en distintos módulos. Lalibrería de módulos predefinidos es tambiénparte del estándar.

. Ampliación, con respecto a Pascal, delconcepto de subtipo y de los criterios decompatibilidad de tipos. En Ada, por ejemplo,todos los arrays de rango finito se consideransubtipos de un array conceptualmente sinlímites. Ello facilita la construcción deprocedimientos que pueden ser llamados condiferentes arrays como parámetro.

. Introducción de sobrecarga definida por el pro-gramador. Éste puede asignar el mismo nombreo símbolo (p.e. "+") a operaciones distintas, eincluso a constantes. El compilador deduce porel contexto -siempre que éste no sea ambiguo-la operación nombrada en cada caso.

. Tratamiento elaborado de excepciones. Elusuario puede tratar excepciones predefinidas(p.e. fuera de rango) y definir -y tratar- las suyaspropias (p.e. pila_vacía). A su vez, lasexcepciones pueden ser propagadas,recuperadas, o ambas

cosas a la vez, en diferentes niveles de laestructura del programa.

. Mecanismo de paso de parámetros oculto alprogramador. Éste sólo debe especificar si losmismos han de ser usados en modo lectura -parámetros in-, en modo escritura -parámetrosout-, o en ambos modos - parámetros in out. Elcompilador garantiza esos usos y elige elmecanismo que considere más eficiente (porvalor, por referencia) independientemente deltipo de parámetro.

. Construcción exit para salir prematuramentede un bucle, o de un conjunto de buclesanidados. El control pasa al final del (de los)bucle(s). Esta construcción elimina una de lasposibles utilidades del go-to.

Después de Ada, no ha habido ningún lenguajeinnovador dentro del paradigma imperativopuro. Tampoco se han producido importantesavances metodológicos que hayan hechonecesario diseñar nuevos lenguajes en esteparadigma. Los 80 y los 90 han visto eldesarrollo espectacular de otros paradigmas deprogramación. Se han diseñado muchos otroslenguajes interesantes pero que pertenecen a, oincluyen elementos de, esos otros paradigmas.Su historia se relata en las secciones siguientes.

4 La programación orientada a objetos

Un lenguaje de la década de los 60 que -deliberadamente- no ha sido comentado en laSección 2 es Simula 67. Contiene el embrión delo que hoy se conoce como la programaciónorientada a objetos (en adelante, POO), por loque se ha preferido relatar su historia en estasección. Sus creadores fueron Kristen Nygaard y Ole-Johan Dahl del Centro Noruego deComputación en Oslo [DMN70], y su desarrollose extendió desde 1962 a 1967. El objetivoinicial era definir un lenguaje de propósitoespecífico para aplicaciones de simulación. Dehecho, realizaron una primera versión, bajocontrato con la empresa UNIVAC, que noincluía conceptos novedosos desde el punto devista de programación -aunque sí desde el puntode vista de simulación- con respecto al lenguajemás avanzado de esos años, Algol 60. La versión de 1967 tenía como uno de susobjetivos ahorrar esfuerzo de programación.Nygaard y Dahl habían desarrollado grandesprogramas de simulación con la primeraversión, y habían detectado dos deficiencias:

Page 22: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

12

l. Las entidades proceso y estación, útiles ensimulación, eran entes dinámicos que se creabany destruían a lo largo de una ejecución. Elconcepto de bloque derivado de Algol 60, erainsuficiente para reflejar este dinamismo. Porotra parte, cada entidad tenía asociadas unconjunto de variables y un conjunto deoperaciones que las manipulaban. De nuevo, eltexto del programa no reflejaba claramente estarelación.

2. El código de muchas entidades era bastantesemejante, pero el lenguaje no proporcionaba unmecanismo que permitiera reutilizar las partescomunes. El primer hallazgo de Nygaard y Dahl fue ladistinción entre una clase de entidades -un textosuministrado por el programador- y los objetosque se derivan de ella -los ejemplares de lamisma creados y destruidos dinámicamente a lolargo de una ejecución concreta. Una clase enSimula 67 consiste en una colección deprocedimientos, asociados a un conjunto dedeclaraciones de variable. Cada vez que se creaun objeto de una clase, se asigna memoria paracontener una colección de dichas variables. Estaidea, hoy familiar, exigía dos innovaciones conrespecto a los lenguajes de la época:

. Escapar de la estructura de bloques. A diferen-cia de ésta, un objeto ha de "sobrevivir" al pro-cedimiento que lo crea. Varios objetos de unamisma clase han de poder coexistir en un mismoámbito.

. Necesidad de un tipo de datos "referencia a unobjeto" que permitiera designar objetos distintosen distintos momentos. Este tipo, llamado ref enel lenguaje, no era otra cosa que un puntero.

Esta noción de clase fue enriquecida enlenguajes posteriores con la idea deocultamiento que -como se ha explicado en laSección 3- surgió más adelante, dando lugar alconcepto de objeto que hoy conocemos. Laclase de Simula 67 puede verse como precursoraa la vez de los objetos de la POO y de los tiposabstractos de datos comentados en la Sección 3.De hecho, dejando de lado cuestiones denotación y de terminología, las ideas deencapsulamiento y de abstracción de datos sonexactamente las mismas. El segundo hallazgo de Simula 67 -y éste sí quees específico de la POO- es el concepto desubclase. La idea esencial es simple: si unaclase B ha de repetir declaraciones de variablesy de procedimientos que ya están en otra claseA, se indica que la clase A es un prefijo de laclase B, y se definen en B tan sólo las variablesy los procedimientos que son específicos de B.En [DH72] se denomina a este proceso conca-tenación de clases, pero el término originalempleado

en Simula 67 es el de prefijo, y el de subclasepara la clase definida mediante prefijos. Es obvio que el proceso se puede iterar, y que sepueden construir secuencias C1, . . ., Cn en lasque cada clase Ci+l, i ε {l..n - l}, tiene comoprefijo a la clase Ci. Más aún, una misma claseA puede actuar como prefijo de varias subclasesB1,..., Bm que, en este caso, serían "hijas" deuna misma clase-madre. En [DH72] seproporciona un embrión de método dedesarrollo descendente basado en esta idea dejerarquía de clases. A nivel de implementación,en Simula 67 se reconoce la influencia de[Hoa68] , especialmente en el uso de punteros yen la implementación de las subclases de unamisma clase como registros variantes delregistro que implementa la clase-madre. El siguiente hito en la POO, y en realidad quienle dio categoría de paradigma con característicaspropias, fue el lenguaje Smalltalk. Su creadorfue Alan Kay, del Centro de Investigación enPalo Alto de Xerox Corporation. También eneste caso, la gestación fue larga y laboriosa,desde una primera versión en 1972, hasta laversión pública de 1980 [GR83]. En el caminose desarrollaron varias versiones para usointerno de Xerox. El autor reconoce en [Kay93]influencias de Simula 67, de LOGO y de FLEX,un lenguaje previo desarrollado por él mismo. Los conceptos de clase, objeto de una clase, ysub-clase de una clase son los centrales dellenguaje. A la clase-madre de una subclase se ladenomina superclase de la misma. En Smalltalkaparece ya nítidamente la obligación de que larepresentación de un objeto sea privada y, portanto, oculta a los usuarios de una clase. Otrascaracterísticas de Smalltalk son las siguientes:

. Integración del lenguaje con el entorno de pro-gramación. Smalltalk pone mucho énfasis eneste aspecto, extendiendo los conceptos dellenguaje al propio entorno, que también secompone de objetos. Además, el entorno gráficoque acompaña a Smalltalk, el primero basado eniconos y menús, sirvió de inspiración a todos lossistemas operativos de ventanas que vinierondespués, comenzando por los de loscomputadores de Xerox y de Apple.

. Comprobación de tipos en ejecución.

. Polimorfismo de subtipos, que se define comoel hecho de que un objeto de una subclase esadmisible en cualquier parte del programadonde sea válido un objeto de su superclase.5

----------------------------------------------------------

5Algunos autores llaman polimorfismo, sincalificativo, a esta característica. Aquí se hareservado este término para el polimorfismoparamétrico de los lengajes funcionales queposeen el sistema de tipos de Hindley-Milner[Mil78]. Ver la Sección 7.

Page 23: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

13

. Vínculos dinámicos entre identificadores yobjetos. En Smalltalk, un procedimiento de unaclase puede ser redefinido en una subclase de lamisma. Por ello, se difiere al momento de laejecución la decisión de qué versión utilizar deun procedimiento dado, cuando existen variasversiones del mismo.

. Librería predefinida, de clases y subclases,muy voluminosa. Se contempla la tarea delprogramador más como la de enriquecerinteractivamente dicha librería con subclases deotras clases ya existentes, que como la de crearclases nuevas desde cero.

. Incorporación de un algoritmo implícito derecolección de basura.

. Máquina virtual de soporte al lenguaje que seha convertido en un estándar para los lenguajesorientados a objetos.

A partir de Smalltalk y de su "filosofía"asociada -"todo" son objetos, creación dinámicade objetos, librería predefinida de clases,entorno gráfico interactivo- se produce uninterés muy grande por el paradigma, y la POOse difunde ampliamente en entornosindustriales. Se considera que la orientación aobjeios consiste, no sólo en unas facilidades deciertos lenguajes de programación, sino tambiénen un modo de enfocar el diseño de grandesprogramas. Muchos libros sobre ingeniería delsoftware asumen el paradigma y hablan de cons-trucción, diseño y modelización "orientados aobjetos" [Cox86, Mey88, Boo91, RBP+91]. En realidad, la POO no constituye un paradigmaalternativo al imperativo en el mismo sentidoque lo son la programación funcional o laprogramación lógica. Por un lado, los lenguajesorientados a objetos son sin duda imperativos.Por otro, las ideas originales subyacentes -enesencia, el concepto de herencia por el cual unasubclase hereda los atributos de clasessuperiores en la jerarquía-, son útiles encualquier paradigma. De hecho, estamosasistiendo en estos años al surgimiento delenguajes que combinan estas ideas con laspropias de su paradigma: lenguajes funcionalesorientados a objetos, lenguajes lógicosorientados a objetos, e incluso lenguajes lógico-concurrentes orientados a objetos. Desde el punto de vista práctico, la POO aportauna forma de programar que pone el acento enla reutilización del software. Antes deplantearse programar una nueva clase, elprogramador ha de ser consciente de las que yaexisten, y tratar de contemplar su clase comoderivada de otra (u otras) previas. Ello le obliga,por un lado, a un esfuerzo de clasificación,descubriendo conexiones entre módulosaparentemente

no relacionados y, por otro, a un esfuerzo degeneralización, creando clases genéricas quepuedan ser superclases de muchas otras. Ambastareas son beneficiosas para una programaciónen gran escala. Además, la POO es conscientede que la reutilización lleva aparejado un ciertogrado de adaptación. Por ello, los lenguajesorientados a objetos permiten, no sólo ampliarlas definiciones con respecto a las de lasuperclase, sino también redefinir algunas de lasoperaciones de la misma, si bien manteniendosiempre el mismo perfil externo. Conviene hacer notar, no obstante, que lo que sereutiliza de una clase es su implementación. Elocultamiento de información de una clase haciasus programas usuarios desaparece cuando setrata de las subclases. Ello va ciertamente encontra de la idea original de modularidad, segúnla cual se puede cambiar la implementación deun módulo de manera transparente al resto delos mismos. Si se modifica la implementaciónde una clase situada muy arriba en la jerarquíade clases, muchas subclases habrán de serreprogramadas, ya que la nueva implementaciónprobablemente no podrá ser extendida de lamisma manera que lo era la antigua. A nivel más teórico, la relación clase-subclasees una generalización del concepto de subtipoen programación. Un subtipo es unaespecialización de un tipo, que hereda todas lasoperaciones del tipo-padre (o supertipo), y quepuede añadir algunas otras. Un valor de unsubtipo es admisible en cualquier parte del textodonde se espere un valor de su supertipo (vercomentario acerca de los subtipos de Ada en laSección 3). La POO ha despertado un renovadointerés por los sistemas de tipos en los lenguajesde programación. En particular, un registro queextiende a otro con campos adicionales, secontempla actualmente como un subtipo delprimero. Para obtener una panorámica de ladiversidad que pueden alcanzar estos sistemas,ver [CW85] y [Car89]. Una consecuencia del movimiento de la POO esque se han producido versiones de lenguajesexistentes -en muchos casos superconjuntos-que incorporan características orientadas aobjetos. El caso más evidente es el de C++[Str86b, Str86a], prácticamente unsuperconjunto de C [KR78]. La construcciónmodular de C++ también se llama clase, ypermite tanto la definición de tipos abstractos dedatos como la utilización de los conceptos deherencia. En C++ se refuerza la disciplina detipos con respecto a C y, a diferencia deSmalltalk, la comprobación de tipos es estática.Otras diferencias con Smalltalk son que C++admite herencia múltiple -es decir, una clasepuede heredar los atributos de dos o más clasessimultáneamente- y que la gestión de memoriasigue el esquema de bloques: los objetos secrean al

Page 24: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

14

declararlos y se destruyen al abandonar elbloque. Otro lenguaje que ha sufrido unametamorfosis parecida es Modula-2: el lenguajedel mismo autor, Oberon [Wir88] , añade sobreModula-2 la construcción de registrosextensibles que no es sino otro nombre para laidea de subclase. También Ada ha evolucionadoen la misma línea: la reciente revisión Ada 95[Ada95] incorpora el concepto de herencia yuna librería estructurada de clases. Un lenguaje moderno especialmente diseñadopara la programación orientada a objetos engran escala es Eiffel [Mey88, Mey92]. Incluyedisciplina fuerte de tipos, comprobaciónestática, genericidad, herencia múltiple,vínculos dinámicos, operaciones diferidas(indefinidas en la superclase pero definidas enlas subclases) y recolección automática debasura.

5 La programación concurrente

En la Sección 2 se ha mencionado el invento dela interrupción a finales de los 50 como el hechoque marca el inicio de la programaciónconcurrente. El desarrollo de los conceptosadecuados para este tipo de programación ha idosiempre a remolque de los avances enarquitectura de computadores. Los comienzosfueron extremadamente difíciles, pues seconstruían sistemas operativos muy complejos,como el mencionado OS/360 de IBM, sincomprender apenas las implicaciones del hechode compartir datos entre procesos que podíanser interrumpidos y recontinuados en instantesarbitrarios. Fallos que aparecían en unaejecución, no volvían a aparecer en lassiguientes, haciendo muy difícil la tarea dedepuración. Eran los temibles erroresdependientes del tiempo, específicos de laprogramación concurrente. Las primeras abstracciones las proporciona E.W. Dijkstra en una sucesión de trabajos [Dij65,Dij68b, Dij68d, Dij71] que fueron de unainfluencia decisiva para la comprensión delproblema. Dijkstra observó que la inmensamayoría de los errores era debida a suposicionesimplícitas que el programador de un procesohacía acerca del instante de ejecución en que sehallaban otros procesos. Cuando esassuposiciones eran invalidadas por pequeñasvariaciones en las velocidades, se producía elfallo. La aportación principal -hoyabsolutamente natural, pero nada evidente enaquel momento- fue concebir el programaconcurrente como un conjunto de procesossecuenciales asíncronos que no debían hacersuposiciones implícitas sobre las velocidadescon que progresaban los otros procesos.Cualquier relación de orden temporal entre elloshabía de conseguirse por medio desincronizaciones explícitas. Con este fin,propuso el

mecanismo del semáforo. Éste consiste, enesencia, en una variable entera compartida, condos operaciones, llamadas P y V, que seejecutan en exclusión mutua. Los semáforos sirven para crear regionescríticas en las que un proceso consigueexclusión mutua con respecto a otros en elacceso a un recurso, o para proveer cualquierotra sincronización. Sin embargo, comomecanismo para incorporar a un lenguaje espoco seguro. Una operación V de más sobre elsemáforo, o de menos, puede producir efectoscatastróficos. Por ello, Hoare propone, en[Hoa72c], las regiones críticas y las regionescríticas condicionales (en adelante, RCC's)como construcciones estructuradas a serincluidas en un lenguaje concurrente. Laprimera suministra exclusión mutua y lasegunda proporciona además sincronización.Ésta se produce evaluando en exclusión mutuauna expresión booleana sobre variablescompartidas: si la expresión es cierta, el procesoprosigue; en caso contrario, libera la exclusiónmutua y queda detenido hasta que la expresiónsea cierta. P. Brinch Hansen populariza estasconstrucciones en [Han72] y [Han73], y sugierealgunas variantes. Las RCC's resultan bastante expresivas, peroadolecen de dos problemas: el más grave deellos es que son ineficientes de implementar.Cada vez que un proceso sale de una RCC, elgestor de procesos "despierta" a todos losprocesos esperando por alguna condición y, porturno, reevalúan cada uno la suya. Si algunovuelve a encontrar que su condición es falsa, esdetenido de nuevo. El fenómeno puede repetirsemuchas veces antes de que la condición seacierta, y en consecuencia, los procesosconsumirían tiempo del procesador inútilmente.El segundo problema es que, en un programagrande, las RCC's -cada una referida a unrecurso compartido posiblemente distinto-quedan dispersas en el texto de los procesoshaciendo difícil el control del uso de lasvariables compartidas. Ambos problemas sonresueltos por una nueva construcción: elmonitor. Anticipado por Dijkstra en [Dij71] conel nombre de "secretario", su introductor comoconstrucción acabada de lenguaje es Hoare en[Hoa74]. El concepto de monitor está inspirado en lasabstracciones de datos de la programaciónsecuencial, y consiste en una colección deprocedimientos y en un conjunto de variablescompartidas por ellos. La diferencia es queahora los procedimientos pueden ser llamadosconcurrentemente desde varios procesos. Cadaprocedimiento se ejecuta en exclusión mutuacon los demás -o consigo mismo, si es llamadopor dos procesos-, suministrando así elequivalente a la región crítica. Para sincronizarunos procesos con otros, los monitores puedendeclarar variables condición y realizar sobreellas dos operaciones, llamadas

Page 25: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

15

comúnmente wait y signal, cuyo efecto es muysimilar al de las operaciones P y V de lossemáforos. De esta manera, el monitor seconvierte en un mecanismo de encapsulamientode recursos compartidos y de modularidad parala construcción de programas concurrentes. P.Brinch Hansen desarrolló el lenguajeConcurrent Pascal [Han75] basado en esteconcepto. Era el primer lenguaje concurrente dela historia, y para demostrar su utilidad,programó con él varios sistemas operativos[Han76, Han77]. Otros lenguajes concurrentesposteriores que incorporan monitores sonModula [Wir77], Mesa [MMS79, LR80] yPascal Plus [WB79]. Pero, apenas nacidos, los monitores yaresultaban un mecanismo insuficiente. Hacia1975, se habían empezado a fabricar losprimeros microprocesadores y, en muy pocotiempo, dominarían el mercado gracias a su bajocoste. Era evidente que la concurrencia en unsolo procesador sería desplazada a medio plazopor una verdadera programación paralela en laque diferentes procesos se ejecutarían endiferentes procesadores. La suposición -implícita en los monitores y en los mecanismosprecedentes- de una memoria común en la queresidían las variables compartidas por losprocesos, dejaba de ser realista. Se necesitabauna construcción que pudiera implementarsemediante el paso de mensajes entreprocesadores. Se realizan varias propuestas[Hoa78, Han78, MY80], de las cuales la que hatenido más influencia es la de los ProcesosSecuenciales Comunicantes (CSP-78) de Hoare.

La comunicación en CSP-78 se realiza medianteun paso sincronizado de mensajes o cita. Elprimer proceso -lector o escritor de un mensaje-que llega al punto de cita, espera al otro.Cuando ambos están dispuestos, se produce lacomunicación. Adicionalmente, un procesopuede estar en una espera no determinista porvarias citas. La primera que sea posible, porestar ya dispuesto el proceso complementario,es la que se produce. Para expresar esta esperano determinista, Hoare utiliza una construcciónsimilar a las acciones protegidas (guardedcommands) del lenguaje secuencial de Dijkstra[Dij75]. Con ella consigue una expresividadequivalente a la de las RCC's, ya que lascondiciones de sincronización -llamadas aquíguardas- son expresiones booleanas, pero sin laineficiencia asociada a aquellas. Un lenguajeque implementa directamente las ideas de CSP-78 es Occam [Occ84] , desarrollado por laempresa INMOS Ltd. como lenguaje base parasus redes de transputers. Un transputer es unmicrocomputador con unas capacidadesmejoradas de comunicación. Occam incorporacanales entre procesos, idea que ya fue anti-cipada en [Hoa78].

El segundo lenguaje influido por la propuestaCSP-78es Ada [Ada83]. La sincronización en Ada esmás elaborada que la de CSP-78 porque aquí lacita involucra mensajes en dos direcciones:primero, de la tarea llamante a la tarea llamadapara pasar los parámetros de entrada, y luego ensentido contrario para devolver los posiblesresultados. En lugar de canales, el mecanismode comunicación es mediante llamada remota.Es, por tanto, asimétrico en el sentido de que latarea cliente o llamante "conoce" a la tareaservidora o llamada, pero no a la inversa. Comovarias tareas cliente pueden llamar a la mismaentrada remota de una tarea servidora, Adaprovee una cola FIFO por entrada para gestionarlas esperas. En Ada existe también elequivalente a las acciones protegidas nodeterministas de CSP-78: mediante lainstrucción select, una tarea servidora puedeestar a la espera de que llamen a cualquiera desus entradas. Otras facilidades concurrentespresentes en Ada, pero no en CSP-78, serefieren al control sobre el tiempo real y sobrelas interrupciones de los periféricos externos.

Recientemente, se ha producido una importanterevisión de Ada [Ada95] que ha afectado sobretodo a los aspectos concurrentes del lenguaje.Además de mantener el mecanismo distribuidode las tareas, se ha incorporado otro, llamadotipos protegidos, que se utiliza para compartirdatos en un mismo procesador. La construcciónes una versión de monitor bastante elegante yaque la sincronización se produce medianteexpresiones booleanas, llamadas aquí barreras.Sin embargo, ha escapado al problema de laineficiencia haciendo que, a lo sumo, exista unabarrera por procedimiento y que ésta sóloincluya variables locales del monitor. Se añadeuna primitiva requeue para suplir laimposibilidad de tener varias barrerasconsecutivas en un mismo procedimiento. Larazón principal de los tipos protegidos esaumentar la eficiencia de la sincronización entreprocesos.

En el área de la programación concurrente, losmétodos de verificación y de razonamientosobre la corrección de los programas no hanalcanzado la misma estabilidad que en el casode la programación secuencial. Los primerosintentos consistieron, siguiendo los pasos deesta última, en aplicar las técnicas deespecificación con predicados. En [Hoa72c] seextienden los axiomas de las construccionessecuenciales con reglas para tratar con lasRCC's y con la instrucción paralela cobegin. . .coend. Estas reglas tienen excesivasrestricciones sobre el tipo de variables quepueden aparecer en los asertos. La primeralógica completa para verificar la correcciónparcial de programas concurrentes basados enRCC's la proporciona la tesis de Susan Owicki

Page 26: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

16

[Owi75, OG76]. La técnica de verificaciónexige que se demuestre la llamada propiedad de ausencia de interferencia entre los asertos decada proceso y las acciones elementales detodos los restantes. Ello da lugar a un esfuerzode demostración proporcional al ¡cuadrado! dela longitud del texto. Para disminuir esteesfuerzo, se proponen algunas técnicas como ladel invariante global: un predicado que puedenombrar variables locales a los procesos yvariables compartidas entre ellos, y que espreservado por todas las acciones atómicas delprograma. La técnica de Owicki y Gries permiteverificar la conservación de la exclusión mutuay la ausencia de bloqueo. La idea de que un programa concurrente, enesencia, mantiene un invariante global, pareceestar presente en todas las técnicas que se hanpropuesto posteriormente. Son especialmenterelevantes los numerosos trabajos de LeslieLamport. En [Lam77] se proponen los términospropiedades de seguridad y de vitalidad hoycompletamente aceptados. En [Lam80] seintroducen los predicados at, in y after pararazonar sobre el valor del contador de programade cada proceso, y una lógica generalizada parademostrar propiedades arbitrarias de seguridad yde vitalidad, en la que el invariante global juegaun papel preponderante. En [LS84] relaciona sumétodo con el de Owicki y Gries y muestracómo es también aplicable a programas escritosen CSP-78. Una variante de la lógica simple de predicadoses la lógica temporal, introducida originalmentepor A. Pnueli en [Pnu77]. Esta lógica permiterazonar sobre secuencias de estados y expresarpropiedades de obligatoriedad tales como "elestado P conduce inevitablemente al estado Q".En contrapartida, las verificaciones son máscomplejas. En [OL82], Owicki y Lamportdemuestran propiedades de vitalidad usandológica temporal e invariantes. Se han re-copilado los resultados fundamentales de lainvestigación en lógica temporal en [MP92]. L.Lamport ha desarrollado recientemente unlenguaje muy simple, con una lógica temporalasociada, para razonar cómodamente sobre laspropiedades de vitalidad de los sistemas[Lam94]. En [AFdR80] se propone también un conjuntode reglas de verificación para CSP-78, pero estavez en el marco de la lógica simple depredicados. También en este marco, Hoare dioen [Hoa74] las reglas de verificación paramonitores. De nuevo, el invariante del monitores una pieza fundamental. En un programa conmonitores, el invariante global es, simplemente,la conjunción de los invariantes de todos losmonitores, y se puede suponer que se satisfaceen cualquier punto de un proceso que seaexterior a las llamadas a monitores. Otro sistema para el razonamiento sobreprogramas concurrentes basado en lógica de

predicados es el lenguaje UNITY [CM88].Aquí, el programa se concibe como una ejecución no determinista deasignaciones atómicas. UNITY no es, pues, unlenguaje de programación convencional, perotiene muchos elementos de éstos: variables,asignaciones, expresiones condicionales, etc.Asociada al lenguaje, se proporciona una lógicacon algunos operadores temporales, tales comoleads-to, que expresa el progreso inevitabledesde un estado a otro. Finalmente, existe en ellenguaje una noción implícita de justicia(fainess) , según la cual no está permitido diferirindefinidamente la ejecución de ninguna acciónelemental. Con estos elementos, en [CM88] severifican muchos ejemplos clásicos, y otros notan clásicos, de la programación concurrente.Quizás la principal debilidad de UNITY es laausencia de una noción de proceso. Ello haceque la transformación de un programa UNITY aun lenguaje concurrente convencional sea unatarea nada formal y pueda perderse, por tanto, lacorrección obtenida con tanto esfuerzo. El concepto de justicia en los sistemasconcurrentes también ha dado lugar anumerosos trabajos. En la mayor parte de losprogramas no es posible demostrar propiedadesde progreso o de terminación si no se hacealguna hipótesis sobre la justicia del lenguajesubyacente. Hay varios tipos de justicia -incondicional, débil, fuerte, etc.- y, según la quese escoja, la técnica de demostración depropiedades será de un modo o de otro. En[Fra86] se encuentra una recopilación detrabajos, y en los libros recientes [AO91] y[Fra92] se muestra como probar la terminaciónde un programa concurrente -y unapostcondición asociada a la misma- bajohipótesis de justicia fuerte sobre el lenguaje. Finalmente, otra linea de investigación muyprolífica ha sido la de los modelos algebraicospara especificar sistemas concurrentes. Estosmodelos algebraicos están basados en unospocos operadores, y no pretenden ser unlenguaje de programación sino más bien unmarco formal en el que especificar, transformary demostrar propiedades de un sistemaconcurrente, a un alto nivel de abstracción, sintener que involucrarse en los detalles de unlenguaje ejecutable. Robin Milner inauguró lalínea con el modelo CCS [MiI80] -posteriormente refinado en [MiI89]-, y fuepronto seguida por el modelo CSP-85 de Hoare[BRH84, Hoa85] y otros modelos [BK85,Hen88]. Los elementos de estos lenguajes sonpocos y simples: ecuaciones recursivas,acciones atómicas -denominadas eventos-,operadores para componer secuencialmente unevento y un proceso, para abstraer parte de loseventos de un proceso, y operadores binariosque componen dos procesos en paralelo, opermiten elegir entre dos procesos alternativos.

Page 27: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

17

La semántica de los sistemas así construidos sesuele dar de tres formas complementarias:

Operacional El lenguaje define un conjunto dereglas de transición que indican cómo untérmino sintáctico evoluciona hacia otrostérminos mediante la "ejecución" de eventos.

Denotacional Un sistema denota un objetocomplejo en un dominio matemático. Estosobjetos son conjuntos definidos recursivamentea partir de la estructura sintáctica del lenguaje.Una componente importante de los mismossuelen ser las trazas, o secuencias de eventos,que el sistema puede ejecutar. Dos sistemas soniguales, si denotan al mismo objeto.

Axiomática Se establecen una serie de axiomasalgebraicos que han de verificar los operadoresdel lenguaje. Dos sistemas sintácticamentedistintos son iguales, si existe una demostraciónutilizando los axiomas y las propiedadesderivadas de los mismos, que transforma uno enel otro.

Cualquiera de las tres formas produce sistemasde cálculo con la potencia de las máquinas deTuring y, por tanto, indecidibles. El uso prácticode tales modelos para verificar propiedades otransformar sistemas necesita, pues, importantesdosis de ingenio [HJF85, JF89, Bae90]. Otratécnica importante para demostrar laequivalencia observacional de dos sistemas,concepto central en el modelo CCS, es labisimulación, introducida originalmente por D.Park en [Par81].

6 La programación lógica

El paradigma de la programación lógica estambién un producto de los 70. Su surgimientoes consecuencia de una interacción entre elgrupo de Inteligencia Artificial de laUniversidad de Marsella, dirigido por AlainColmerauer, y profesores del Departamento deLógica Computacional de la Universidad deEdimburgo, encabezados por Robert Kowalski.Este último había colaborado en un trabajo[KK71] que describía el método de resoluciónSL para la demostración de teoremas en lógica.Éste consistía en un refinamiento del principiode resolución de Robinson [Rob65] que, a suvez, utilizaba un algoritmo de unificación,original también de Robinson y publicado en elmismo trabajo [Rob65]6. El método interesó algrupo de Marsella, a la sazón ocupado endesarrollar una herramienta para elprocesamiento de lenguaje natural. Kowalskifue invitado a una estancia de varios dias enMarsella durante el verano de 1971. Segúnrelata el propio protagonista [Kow88] , esos diasfueron

----------------------------------------------------------

6Para este algoritmo se han propuestoposteriormente numerosas implemenlacioneseficientes. Ver p.e. [MM82].

muy productivos. Descubrieron que había unacercanía muy grande entre el concepto dededucción en lógica y la idea de cómputo enprogramación. Pudieron escribir predicadosrecursivos "ejecutables" para funciones sencillascomo la suma y el factorial. La visita se repitióen la primavera de 1972. Fue después de estavisita cuando el grupo de Colmerauer decidiórestringir la forma de los predicados a lasclaúsulas de Horn, es decir, a predicados de laforma B1 Λ ...Λ Bn → A, con n >=0. Laresolución SL es, en ese caso, más eficiente. Usando cláusulas de Horn, y la resolución SLmodificada como método de deducción,Colmerauer y sus colaboradores definieron eimplementaron el lenguaje PROLOG durante elverano de 1972, y escribieron en PROLOG unlargo programa para procesamiento de lenguajenatural [CKPR73]. El lenguaje fue llamado asícomo abreviatura de Programmation enLogique, a sugerencia de la mujer de PhilippeRoussel. Por su parte, Kowalski publicóresultados más generales sobre programaciónlógica ese mismo año [Kow72]. Un programa PROLOG consta de un conjuntode cláusulas de Horn. Una cláusula se escribe A ← Bl, ..., Bn, donde A recibe el nombre decabeza de la cláusula, y a B1 ...Bn se les llamapremisas o subobjetivos. El programa puede serinterrogado mediante un predicado-preguntaconsistente en una conjunción Q1, ...,Qm depredicados atómicos con variables a los que sedenomina objetivos. El significado intuitivo dela pregunta es: "¿Existen valores de las variablestales que los objetivos son consecuencia lógicadel programa?". Si la respuesta es afirmativa, elprograma devuelve una posible concreción delas variables. PROLOG utiliza una estrategia sencilla deaplicación de pasos de deducción, quecorresponde a una exploración en profundidaddel árbol de deducciones posibles. Comenzandopor el conjunto de objetivos dados en lapregunta, PROLOG unifica, en cada paso, elobjetivo en curso con la cabeza de algunacláusula y,

. si tiene éxito, elimina el objetivo en curso delconjunto de objetivos aún sin resolver, eincorpora a este conjunto las premisas -si lastiene- de la clausula utilizada. Los objetivos aresolver y las cláusulas a ensayar se escogensecuencialmente, según están escritos en el textodel programa.

. si fracasa, realiza una vuelta atrás(backtracking), y reconsidera la últimaunificación realizada, ensayando nuevascláusulas para ese objetivo.

Page 28: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

18

PROLOG se veía en aquel momento tan solocomo un primer paso hacia la programaciónlógica, ya

que su estrategia inocente de exploración delárbol da lugar a un sistema incompleto dededucción. Un sistema completo se basa en laresolución SLD - Selecting a literal, using aLinear strategy, restricted to Definite clauses-que, en esencia, realiza una selección nodeterminista de las cláusulas y de lossubobjetivos. Su completitud fue demostradapor un doctorando de Kowalski [Hil74]. Sinembargo, convertirla en un lenguaje deprogramación práctico no parecía tarea fácil.Ello hizo que PROLOG se convirtiera, en lapráctica, en el único representante de laprogramación lógica. Por otra parte, sebenefició desde el principio de una muy buenaimplementación, gracias a las ideas de D.Warren [War77]. Éste también modificó lasintaxis del PROLOG de Marsella, y realizó unaimplementación para DEC-10, llamada Prolog-l0, que se convirtió, de hecho, en un estándar,conocido hoy como Prolog de Edimburgo[WPP79]. A los programas lógicos se les puede asignardos tipos de semántica: una operacional, queconsiste informalmente en el conjunto deobjetivos sin variables que son resueltosafirmativamente por el programa, y otradeclarativa, que se define como el modelomínimo del programa. Un modelo es unconjunto de objetivos sin variables que nocontradice el significado lógico de las cláusulasdel programa, es decir, si A ← B1, ..., Bn es unaconcreción de una cláusula del programa, y B1,..., Bn pertenecen al modelo, entonces A ha depertenecer al modelo. La semántica declarativase puede dar también empleando la teoría dedominios de Scott y Strachey [SS71]. Es ésta laaproximación utilizada en el trabajo seminal devan Emdem y Kowalski [vEK76]. Esta doble visión, operacional y declarativa, dalugar a una cierta contradicción en lacaracterización de Prolog:

. Si se pone el énfasis en el aspecto declarativo,se obtiene un lenguaje de muy alto nivel quepuede ser usado como lenguaje deespecificación. El programador sólo ha depreocuparse de expresar en cláusulas la lógicade su problema. Pero, entonces, es muyprobable que el programa que obtenga no seaejecutable, en el sentido de que caerá confacilidad en una cadena infinita de de-ducciones, o de que su ineficiencia seráinaceptable.

. Si se pone el énfasis en el aspecto operacional,el programador ha de ser muy consciente delorden en que se ejecutan las cláusulas y lossubobjetivos dentro de ellas y, por tanto,preocuparse por el flujo de control con el

mismo nivel de detalle con que lo haría en unprograma imperativo. Incluso, es posible queescriba cláusulas cuya semántica declarativa noes la adecuada al problema. Los aspectos declarativos confieren propiedadesoriginales a los programas lógicos que lodiferencian de otros paradigmas: los programasno devuelven un resultado único, admitenmuchos tipos de preguntas distintas y, enmuchos casos, son invertibles. Por ejemplo, unprograma que concatena dos listas se puede usartambién para generar todas las formas posiblesde partir una lista en dos, o un programa queordena una lista se puede usar para generar per-mutaciones de una lista ordenada. En la base deestas propiedades está el mecanismo deunificación, que se comporta de un modosimétrico con respecto al objetivo a resolver -programa "llamante"- y a la cabeza de lacláusula elegida -programa "llamado". Es, encierto modo, un compendio de mecanismos queaparecen diferenciados en otros lenguajes: pasode parámetros en ambas direcciones, ajuste depatrones contra un valor estructurado, yconstrucción de valores estructurados a partir desus componentes. Sus capacidades de deducción lógica hicieronque Prolog fuera seleccionado como el lenguajebase para el proyecto japonés -hoy abandonado-de computadores de la "Quinta Generación".Este ambicioso proyecto se lanzó a comienzosde la década de los 80, y debería haberproducido a finales de la misma unoscomputadores con interfaces hombre-máquinaque procesarían el lenguaje natural, y concapacidades lógicas de razonamiento einferencia muy potentes. Aunque no tuvo eseresultado, sí consiguió popularizar Prolog y laInteligencia Artificial. Y ello, no sólo en Japónsino también en el resto de las potenciasindustriales que, recelosas de un posible éxitojaponés en sus objetivos, invirtieron grandessumas en la investigación en estas áreas. Serealizaron implementaciones comerciales deProlog muy eficientes y el lenguaje se difundiónotablemente en ambientes industriales.Desplazó a Lisp en muchas aplicaciones de laInteligencia Artificial, en particular en laconstrucción de los llamados sistemas expertos,hoy muy extendidos. Prolog no consiste simplemente en programarcon cláusulas de Horn. Ya desde su concepción,incorporó una serie de características añadidascon el fin de obtener un lenguaje deprogramación práctico. Una de las máscontrovertidas es el llamado operador de corte.Es una facilidad con la que el programadorpuede podar explícitamente una parte delespacio de búsqueda. Obviamente, cambia lasemántica declarativa del programa ya que sepueden perder soluciones, pero, cuando noexisten o no interesan tales soluciones, consigueaumentar notablemente la eficiencia de muchos

Page 29: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

19

programas. Además, es útil para implementaruna forma incompleta de negación llamadanegación mediante fa1lo: el predicado not P(X)

tiene éxito si el predicado P(X) falla, yviceversa. La semántica de esta construcción fueestudiada por primera vez en [Cla78]. Otrascaracterísticas extralógicas son ciertospredicados aritméticos, la entrada/salida -que seconcibe como un efecto lateral del programa- yla capacidad de automodificación en ejecución -se pueden eliminar o incorporar cláusulasdurante la misma-, hoy afortunadamente endesuso. La programación lógica admite una ciertaseparación entre los aspectos lógicos y losaspectos de control. En [Kow79] se aboga poresta separación, mostrando que un mismoconjunto de cláusulas admite distintasestrategias posibles para el control. Una de ellases lanzar procesos paralelos que se encarguen deexplorar distintas partes del espacio debúsqueda. Esta estrategia es, además, completaya que, si existe algún nodo con éxito, seráfinalmente alcanzado. El inconveniente es quese exploran en anchura grandes extensiones delespacio y se tarda más en llegar a las soluciones,que están ubicadas en las hojas del árbol. Se handesarrollado numerosos lenguajes concurrentesque refinan esta idea. Algunos de ellos sonPARLOG [CG83], Concurrent Prolog [Sha83] yDelta-Prolog [PN84]. Un conjunto de cláusulas sin premisas se puedeconsiderar como la definición de una serie derelaciones. La unión, la intersección y laproyección de relaciones se pueden expresarfácilmente en un lenguaje lógico. Ello estableceuna conexión natural con los modelosrelacionales de bases de datos, lo cual ha dadolugar a una línea de trabajo consistente en laincorporación de facilidades lógicas a loslenguajes de consulta de bases de datos: son lasllamadas bases de datos deductivas [GM78,GMN84]. Actualmente se está trabajando intensamente enla llamada programación lógica conrestricciones. Esta línea tiene su origen en[JL87] y consiste en enriquecer el lenguajelógico con ciertos dominios predefinidos (p.e.booleanos, reales, dominios finitos) y conrelaciones de igualdad, desigualdad, orden, uotras funciones, en dichos dominios, que puedenser resueltas de modo ad-hoc, al margen dellenguaje lógico. Estas restricciones aumentan ala vez la expresividad y la eficiencia dellenguaje. Los lenguajes funcionales, desarrollados enparalelo con el paradigma lógico (ver la Sección7), han aportado una serie de ideas tales comolas funciones de orden superior, las estructurasinfinitas y la técnica de evaluación perezosa, delas que carece, por lo general, la programaciónlógica. Por otra parte, aunque la basematemática de la programación lógica -las

relaciones- es más general que la de laprogramación funcional -las funciones-, enmuchas partes de un programa lógico secalculan funciones deterministas. En esos casos, la búsqueda de solucionesmúltiples es un mecanismo innecesario ycostoso. Por ello, se han hecho numerososintentos de combinar ambos paradigmas en unsolo lenguaje. Ello implica, no sólo tener laposibilidad de definir funciones en un lenguajelógico, sino también extender la lógica a ordensuperior, incorporar un mecanismo deresolución en dicha lógica y dar una semánticaapropiada a tales construcciones. En [BL86]puede encontrarse una clasificación de variasaproximaciones al problema. Algunos lenguajesen esta línea de trabajo son: LOGLISP [RS82] ,EQLOG [GM84], LEAF [BBLM85], BABEL[MNRA89] Y FLANG [Man91], este último,combinación de lenguaje funcional y delenguaje lógico con restricciones.

7 La programación funcional

En la Sección 3 se ha mencionado el lenguajeLisp [MAE+62] como precursor de loslenguajes funcionales. Si es verdad que Lisp hasupuesto una fuente importante de inspiraciónpara este paradigma, los fundamentos delmismo hay que buscarlos en el cálculo lambda(ver la Sección 1) y en los trabajos de H. B.Curry y R. Feys [CF58] sobre lógicacombinatoria. Puede citarse a Peter Landincomo el impulsor originario del paradigmafuncional, en unos años - los 60- en los que lascorrientes predominantes eran muy diferentes.En su trabajo [Lan65], establece la relaciónexistente entre el modelo computacional delcálculo lambda y el de los lenguajes imperativosde alto nivel del momento, proporcionando unaprimitiva semántica denotacional para unamplio subconjunto de Algol 60. Su familia delenguajes ISWIM [Lan66] -acrónimo de If youSee What 1 Mean- supone una ampliaseparación con respecto a Lisp tanto en la sin-taxis como en la semántica. Sus aportacionespueden resumirse como sigue:

. Abandono de la sintaxis prefija de Lisp enfavor de la infija.

. Introducción de las cláusulas let y where pararealizar declaraciones locales a otra declaraci6n.

. Énfasis en el razonamiento ecuacional sobrelos programas.

. Máquina abstracta SECD, basada en cuatropilas, para interpretar programas funcionales.

Pero la más importante de sus aportaciones fuesu visión de la programación funcional como un

Page 30: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

20

paradigma radicalmente distinto del imperativo,en el que estaba excluida toda noción de estadoo de asignación

destructiva. Más aún, veía su lenguaje como unasintaxis edulcorada para el cálculo lambda, alcual eran traducibles todas sus expresiones. La programación funcional durmió el sueño delos justos durante más de diez años, debidoquizás a que sus lenguajes eran meros objetosde laboratorio que no podían competir eneficiencia con sus hermanos imperativos. Lesacó de este letargo la conferencia de JohnBackus con ocasión de la recepción del premioTuring [Bac78]. En ella -y dándose la paradojade que el premio era debido fundamentalmentea su protagonismo en el desarrollo de Fortran yde Algol 60-, arremetió con tremendacontundencia contra el paradigma imperativo alque describió como un corsé que impedía a losprogramadores pensar con libertad en susalgoritmos. En particular, la instrucción deasignación mereció el nombre de cuello debotella intelectual, ya que obligaba a losprogramadores a pensar cómo realizarimportantes cambios en la memoria a base de"cambiar una palabra cada vez" con dichainstrucción. Como alternativa, propone elparadigma funcional y sus elegantespropiedades de ausencia de efectos laterales,razonamiento ecuacional y ricastransformaciones algebraicas. Para ilustrar estasideas, presenta el lenguaje FP y desarrolla con élnumerosos ejemplos. Su conferencia tuvo elefecto de reactivar y estimular la investigaciónen programación funcional aunque,paradójicamente, las características de FP noson las que han prevalecido después. Éstas sonlas siguientes:

. Backus pone el acento en que la programaciónha de consistir en combinar un número reducidode formas funcionales predefinidas. Éstas noson otra cosa que funciones de orden superior.Lo que no ha prevalecido es su concepción deque el programador no debe poder ampliar elcatálogo de las mismas.

. FP es un lenguaje sin tipos. Todos los objetosson del tipo secuencia, una variedad de listasimétrica heterogénea. Los lenguajes posterio-res tienen disciplina de tipos y sus listas son ho-mogéneas.

. Las funciones FP no declaran sus parámetrosformales. En realidad, toda función toma unsólo parámetro y devuelve un único resultado,ambos de tipo secuencia. Esto da a losprogramas un aspecto críptico. Aunque esposible practicar ese estilo en los lenguajesactuales, la sintaxis de los mismos admite unestilo más convencional y más legible.

A pesar de que FP ha sido extendidoposteriormente, su utilidad principal haconsistido en servir como lenguaje base para laconstrucción de entornos de transformación

de programas funcionales, fin para el que resultamuy apropiado. Fruto del interés hacia la programaciónfuncional es la secuencia de lenguajes que sedesarrollan en diferentes universidadesbritánicas a partir de 1978, cada uno añadiendouna característica novedosa:

Hope Desarrollado en Edimburgo por el equipode Rod Burstall [BMS80], incorpora ajuste depatrones para mejorar la definición defunciones, funciones de orden superiordefinibles por el programador, tipos recursivoscon ajuste de patrones asociado, y tiposabstractos de datos.

ML Desarrollado también en Edimburgo[GMM+78], inicialmente como parte deldemostrador de teoremas LCF, y ampliadoposteriormente con el nombre de Standard ML[Mi184]. Su principal aportación es el sistemapolimórfico de tipos [Mi178], conocido comosistema de Hindley-Milner, que será despuésadoptado por la gran mayoría de los lenguajesposteriores: También incluye la definiciónrecursiva de tipos de datos, tipos abstractos,excepciones, y un elaborado sistema demódulos.

SASL, KRC El primero (St. Andrews StaticLanguage), desarrollado en la universidad de St.Andrews [Tur76] , el segundo (Kent RecursiveCalculator), en la universidad de Kent [Tur81] ,y ambos del mismo autor, David Turner. Estoslenguajes aportan un estilo ecuacional paraescribir las definiciones de función y sustituyenla expresión condicional por la inclusión deguardas booleanas en las ecuaciones. Tambiénañaden la notación currificada para lasfunciones. El segundo de ellos incorpora latécnica de evaluación perezosa y la definiciónabreviada de listas mediante la notaciónconjuntista ZF. 7

Miranda Culminación de los dos anteriores ytambién obra de Turner [Tur85, Tur86].Incorpora el sistema de tipos de Hindley-Milner,evaluación perezosa, ecuaciones con guardas,listas ZF, tipos recursivos, tipos abstractos y,como novedad, secciones y una entrada/salidacompletamente funcional. Su implementación estambién original, pues se realiza mediantetraducción a expresiones con sólo doscombinadores, S y K, utilizando un resultadoteórico de la lógica de combinadores.

Este conjunto de características -incorporadasen tan corto espacio de tiempo- cambiaradicalmente el paradigma funcional. Enparticular, la combinación

Page 31: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

21

----------------------------------------------------------

7Llamada así en honor a los matemáticosZermelo y Fränkel. polimorfismo + orden superior + evaluaciónperezosa confiere al mismo un nivel deabstracción muy elevado. La consecuencia esque escribir algoritmos en un lenguaje funcionalproduce un volumen de líneas de código unorden de magnitud inferior con respecto alparadigma imperativo:

El polimorfismo permite definir algoritmos yestructuras de datos parametrizados en los queel tipo de los parámetros puede ser cualquiera.A diferencia de los mecanismos de genericidadexplicados en la Sección 3, aquí no hayseparación entre la fase de definición y la deconcreción, ni hay que dar un nombre a cadaconcreción. Un tipo polimórfico es ya un tipo -no un esquema de tipo- y una funciónpolimórfica es ya ejecutable -en la genericidadtipo Ada, sólo son ejecutables las concreciones.Ello hace el mecanismo polimórfico más fácilde usar. En contrapartida, las construccionesgenéricas admiten operaciones como parte delparámetro formal y las construccionespolimórficas no.

El sistema polimórfico de Hindley-Milner tieneotras características importantes: existe para elmismo un algoritmo de inferencia automáticagracias a la existencia de tipos principales: unaexpresión, o bien no es tipificable, o si lo es, sutipo es único. Ello tiene dos consecuenciasbeneficiosas: liberar al programador de lanecesidad de declarar explícitamente los tipos, ypermitir que toda la comprobación de tipos seaestática. El programa compilado no necesitaincluir ninguna información de tipos.

El orden superior permite asociar a cadaestructura de datos un conjunto de funcionesque encapsulan los esquemas recursivos másfrecuentes para tratar dicha estructura. Muchasfunciones sobre la estructura no son sinoconcreciones de uno de estos esquemas. El usode orden superior permite así ahorrar esfuerzode programación y, por tanto, disminuir laposibilidad de cometer errores.

El caso de las listas es el más conocido: sumarlos elementos de una lista, multiplicarlos, ocalcular la lista inversa, son concreciones de lafunción polimórfica de orden superior foldrcuyo tipo es (a → b → b) → b → [a] → b.Sustituyendo adecuadamente los tipospolimórficos a y b por tipos concretos, elsegundo parámetro de foldr por un valor de tipob, y la función que constituye su primerparámetro por una función apropiada de tipo a→ b → b, se obtienen los algoritmos arribaexpresados.

La evaluación perezosa consiste en evaluaruna expresión sólo cuando su valor es realmenterequerido por el algoritmo y, aún en ese caso,evaluarla lo menos posible. La estrategiaalternativa se denomina evaluación impaciente,y es la empleada comúnmente por los lenguajesimperativos. El uso de esta técnica deevaluación reporta las siguientes ventajas:

l. Programas que no terminan bajo evaluaciónimpaciente, lo hacen bajo evaluación perezosa. 2. Permite definir funciones no estrictas, esdecir, funciones que pueden dar un resultadodefinido aunque algunos de sus parámetrosestén indefinidos. 3. Permite definir estructuras de datos infinitas(p.e. la lista de todos los números primos). 4. Gracias a ello, es posible plantear laentrada/salida sin salirse del marco funcional:los ficheros se contemplan esencialmente co-mo listas infinitas de caracteres que se vanconsumiendo y produciendo "perezosamente" amedida que sus datos son requeridos por elprograma. 5. La programación con objetos infinitos, y engeneral con un lenguaje perezoso, liberan alprogramador en gran medida del control estrictodel flujo de control. Ello conduce a programasmás concisos y con un grado de generalidadmayor que el de sus contrapartidas impacientes.

Esta superioridad de la evaluación perezosa hasido reconocida por los investigadores [Hug90]y, a partir de Miranda, los lenguajes funcionalesposteriores son en su mayoría perezosos.

Hacia finales de los 80 se percibía que elparadigma estaba suficientemente maduro peroque, no obstante, su impacto en la comunidadno investigadora era mínimo. Uno de losobstáculos detectados fue la ausencia de unlenguaje estándar que, además, reunierasuficientes cualidades de lenguaje "real", esdecir, amplia variedad de tipos numéricos,entrada/salida versátil, módulos, librerías, y unarazonable eficiencia. Se emprendió así eldesarrollo de un nuevo lenguaje que recibió elnombre de Haskell [HW88, HPJW92, HF92] enhonor al matemático Haskell B. Currymencionado al comienzo de esta sección. Pero,esta vez, el desarrollo iba a ser colectivo,mediante un comité creado al efecto con ocasiónde la conferencia FPCA8 de 1987.

----------------------------------------------------------8Functional Programming and ComputerArquitecture. La de 1987 se celebro en Portland(Oregon, USA) en Septiembre.

Page 32: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

22

El objetivo, más que innovar, era reunir yhomogeneizar características ya probadas enotros lenguajes. Sin embargo, durante sudefinición tropezaron con un problemainesperado: los operadores sobrecargados.Descubrieron que este aspecto se trataba de unmodo ad-hoc en cada lenguaje e incluso deformas inconsistentes dentro de un mismolenguaje. Por ejemplo, la igualdad de valores, esconsiderado un operador polimórfico enMiranda (su tipo, empleando sintaxis deHaskell, es (==) :: a → a → Bool) aunque no esaplicable a las funciones ni a los tiposabstractos. En ML se considera polimórfico conrestricciones, empleando el tipo 'a → 'a → Boolpara indicar este polimorfismo restringido. Sinembargo, ML trata otros operadoressobrecargados (p.e. +, -, *) de un modo distinto:el lenguaje "sabe" que lo están y la deducciónde tipos es especial en estos casos (p.e. + es aveces de tipo Int → Int → Int y a veces de tipoFloat → Float → Float). El programador nopuede sobrecargar más estos símbolos, comotampoco puede sobrecargar la igualdad -impidiendo, por ejemplo, que el programadordefina su propia igualdad para los tiposabstractos, algo que sería razonable poder hacer.

La solución vino de la mano de una propuestade Philip Wadler y Stephen Blot [WB89] en laque los operadores sobrecargados se agrupan enclases de tipos. Así, los operadores +, - y * seagrupan en la clase Num de los tipos numéricos,y las operaciones ==, y /= en la clase Eq de lostipos con igualdad. Por, ejemplo, el tipo de + seexpresa como Num a => a → a → a paraindicar un polimorfismo restringido a los tiposde la clase Num. La definición de una claseprovee el nombre y el tipo de los operadores, yalgunas ecuaciones opcionales por defecto. Paraincorporar un tipo concreto a una clase, elprogramador ha de suministrar una concreciónde la clase -construcción instance- para esetipo. En dicha concreción se dan las ecuacionesque definen, para ese tipo, los operadoressobrecargados. De este modo, la sobrecarga esuna facilidad general del lenguaje controlablepor el programador. En [WB89] se dan tambiénlas modificaciones necesarias al algoritmo deinferencia del sistema de tipos de Hindley-Milner para tener en cuenta la presencia deoperadores sobrecargados, y una semántica detraducción que convierte un programa conoperadores sobrecargados en otro tipificable enel sistema de Hindley-Milner puro. La inclusión de clases es la característicasingular que más diferencia a Haskell de loslenguajes precedentes. La combinación desobrecarga y polimorfismo produce efectoscomparables a los de la genericidad, pero sin el

barroquismo de aquella. Por ejemplo, se puedeprogramar genéricamente el algoritmo quicksortutilizando la comparación sobrecargada <=. El

tipo resultante es Ord a => [a] → [a]. Ello haceutilizable a quiclsort para listas de cualquier tipode datos que pertenezca a la clase Ord. Otrascaracterísticas interesantes de Haskell son lassiguientes:

. Sistema de módulos que permite unavisibilidad controlada de los identificadores porparte del programador, con directivas paraexportar, importar y reexportar los mismos.Compilación separada.

. Sofisticada entrada/salida, tanto en modo textocomo en modo binario, a dispositivos con-vencionales y a ficheros en disco. La versión 1.3del lenguaje, de Junio de 1995 [Has95], incluyeun modelo de entrada/salida basado en mónadas[Mog89], que hace más intuitiva al programadorla escritura de sus programas. Este modelo esresultado de una linea de trabajo recienteiniciada por Wadler en [Wad92] y continuadaen [PJW93].

. Facilidad para definir tipos abstractos, nocomo una construcción especial, sino como unaconsecuencia del sistema de módulos: un tipoabstracto es un tipo algebraico definido en unmódulo, del cual no se exportan susconstructoras. Como consecuencia, los módulosusuarios no pueden construir valores del tipodirectamente ni hacer ajuste de patrones sobrevalores del mismo.

. Inclusión de arrays como tipo abstractopredefinido. Su tamaño se decidedinámicamente. Una programación cuidadosacon arrays junto con un compilador"inteligente", o el empleo de las técnicas deprogramación con mónadas [Hud93, Lau93],permiten garantizar que los arrays sonactualizados in situ y, por tanto, con costeconstante. Ello abre a la programación funcionalalgoritmos y estructuras de datos (p.e. tablashash) que eran patrimonio tradicional de laprogramación imperativa [NPP95].

Referencias

[Ada79] Preliminary Ada Reference Manual.SIGPLAN Notices, 14(6A), June 1979. [Ada83] Reference Manual for the AdaProgramming Language. ANSI/MIL-STD-1815A- 1983,1983. [Ada95] Reference Manual for the AdaProgramming Language. ISO/IEC 8652:1995,1995. [AFdR80] K. R. Apt, N. Francez, and W. P. deRoever. A Proof System for Communicating

Page 33: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

23

Sequential Processes. ACM TOPLAS, 2:359-385, 1980.

[AHU83] A. V. Aho, J. E. Hopcroft, and J. D.Ullman. Data Structures and Algorithms.Addison- Wesley, 1983. [AO91] K. R. Apt and E.-R. Olderog.Verification of Sequential and ConcurrentPrograms. Springer- Verlag, 1991. [Bac78] J. Backus. Can Programming BeLiberated from the Von Neumann Style? AFunctional Style and Its Algebra of Programs.Comm. ACM, 21(8):613-641, August 1978. [Bae90] Applications of Process Algebra.Cambridge University Press, Cambridge, 1990.J. C. M. Baeten (editor). [BBLM85] R. Barbuti, M. Bellia, G. Levi, andM. Martelli. LEAF: A Language whichintegrates Logic, Equations and Functions. InLogic Programming: Functions, Equations andRelations. Prentice Hall, 1985. D. DeGroot andG. Lindstrom (editors). [BJ66] C. Bohm and G. Jacopini. FlowDiagrams, Turing Machines and Languageswith only two Formation Rules. Comm. ACM,9(5), May 1966. [BK85] J. A. Bergstra and J. W. Klop. Algebraof Cornmunicating Processes with Abstraction.Theoretical Computer Science, 37:77-121,1985. [BL86] M. Bellia and G. Levi. The Relationbetween Logic and Functional Languages.Journal of Logic Programming, 3:217-236,1986. [BMPW86] M. Broy, B. Möller, P. Pepper, andM. Wirsing. Algebraic ImplementationsPreserve Program Correctness. Science ofComputer Programming, 7:35-37, 1986. [BMS80] R. M. Burstall, D. B. McQueen, andD. T. Sannella. HOPE: An Experimental AplicativeLanguage. In The 1980 LISP Conference, pages136-143. Stanford and Santa Clara Universities,1980. [Boo91] G. Booch. Object-Oriented Design.Benjamin/Cummings, 1991. [BRH84] S. D. Brookes, A. W. Roscoe, and C.A. R. Hoare. A Theory for CommunicatingSequential Processes. Journal of the ACM,31:560-599,1984. [BW84] M. Broy and M. Wirsing. A SystematicStudy of Models of Abstract Data Types.Theoretical Computer Science, 33: 139-174,1984. [Car89] L. Cardelli. Typeful Programming.DEC SRC Report no. 45, 1989. [CF58] H. B. Curry and R. Feys. CombinatoryLogics, volume l. North-Holland, 1958.

[CG83] K. L. Clark and S. Gregory. PARLOG:a Parallel Logic Programming Language.Technical Report 83/5, Imperial College,London, 1983. [Cho56] N. Chomsky. Three Models for theDescription of Language. IRE Transactions onInformation Theory, 2(3):113-124, 1956. [Chu41] A. Church. The Calculi of LambdaConversion. Princeton University Press, NewJersey, 1941.

[CKPR73] A. Colmerauer, H. Kanoui, R.Pasero, and P. Roussel. Un Systeme deCommunication Homme-Machine en Franaçais.Technical report, Groupe d'lntelligenceArtificielle, Univ. de Aix-Marseille II, 1973. [Cla.78] K. L. Clark. Negation as Failure, pages293-332. Plenum Publishing. See [GM78],1978. [CM88] K. M. Chandy a.nd J. Misra. ParallelProgram Design: A Foundation. AddisonWesley, Reading, Massachusetts, 1988. [Cox86] B. J. Cox. Object-OrientedProgramming: An Evolutionary Approach.Addison-Wesley, 1986. [CW85] L. Cardelli and P. Wegner. OnUnderstanding Types, Data Abstraction, andPolymorphism. Computing Surveys, 17(4):471-522, December 1985. [Dah78] O.-J. Dahl. Can Program Proving bemade Practical? Institute of Informatics.University of Oslo. Norway, 1978.

[DH72] O.-J. Dahl and C. A. R. Hoare.Hierarchical Program Structures. In StructuredProgramming, pages 175-220. Academic Press,1972. ver [DHD72]. [DHD72] E. W Dijkstra, C. A. R. Hoare, andO.-J. Dahl. Structured Programming. AcademicPress Inc., 1972. [Dij65] E. W. Dijkstra. Solution of a Problem inConcurrent Programming Control. Comm.ACM, 8(9), September 1965. [Dij68a] E. W. Dijkstra. A ConstructiveApproach to the Problem of ProgramCorrectness. BIT, August 1968. [Dij68b] E. W. Dijkstra. Cooperating SequentialProcesses. In F. Genuys, editor, ProgrammingLanguages, pages 43-112. Academic Press,1968. [Dij68c] E. W. Dijkstra. Go-to StatementConsidered Harmful. Comm. ACM, 11(3):147-148, March 1968. [Dij68d] E. W. Dijkstra. The Structure of theTHE Multiprogramming System. Comm. ACM,11(5):341-346, May 1968. [Dij71] E. W. Dijkstra. Hierarchical Ordering ofSequential Processes. Acta Informatica,1(2):115-138, 1971. Also in Operating System

Page 34: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

24

Techniques, Academic Press 1972, C. A. R.Hoare and R. H. Perrott (editors).

[Dij72a] E. W. Dijkstra. The HumbleProgrammer. Comm. ACM, 15(10):859-866,October 1972. [Dij72b] E. W. Dijkstra. Notes on StructuredProgramming. In Structured Programming,pages 1-82. Academic Press, 1972. ver[DHD72]. [Dij75] E. W. Dijkstra. Guarded Commands,Nondeterminacy and Formal Derivation ofPrograms. Comm. ACM, 18(8):453-457, August1975. [Dij76] E. W. Dijkstra. A Di.fcipline oJProgramming. Prentice-Hall, 1976. [DMN70] O.-J. Dahl, B. Myhrhaug, and K.Nygaard. The Simula 67 Common BaseLanguage. Norwegian Computing Center, Oslo,Pub. S-22, 1970. [DoD60] COBOL, Initial Specifications for aCommon Oriented Business Language.Department of Defense. Washington D.C., U.S.Goverment Printing Office, No. 1960 O-552133, 1960. [DoD61] COBOL, Revised Specifications for aCommon Oriented Business Language.Department of Defense. Washington D.C., U .S.Goverment Printing Office, No. 1961 O-598941, 1961. [EKMP82] H. Ehrig, H. J. Kreowski, B. Mahr,and P. Padawitz. Algebraic Implementation ofAbstract Data Types, volume 20 of TheoreticalComputer Science, pages 209-263. North-Holland,1982. [EM85] H. Ehrig and B. Mahr. Fundamentals ofAlgebraic Specification 1, volume 6 of EATCSMonographs on Theoretical Computer Science.Springer-Verlag, 1985. [FGJM85] K. Futatsugi, J.A. Goguen, J.-P.Jouannaud, and J. Meseguer. Principles ofOBJ2. Proc. 12th ACM Symp. on Principles ofProgramming Languages, pages 52-56, 1985.New Orleans. [Flo67] R. Floyd. Assigning Meaning toPrograms. In Actas del American MathematicalSociety Symposium on Applied Mathematics,pages 19-32,1967. [Fra86] N. Francez. Fairness. Springer- Verlag,1986. [Fra92] N. Francez. ProgramVerification. Addison- Wesley, 1992. [GH86] A. Geser and H. Hussmann.Experiences with the RAP system, aspecification interpreter combining termrewriting and resolution. Springer LNCS,213:339-350, 1986. European Symp. onProgramming.

[GHM78a] J. V. Guttag, E. Horowitz, and D.Musser. Abstract Data Types and SoftwareValidation. Comm. ACM, 21(12):1048-1064,December 1978.

[GHM78b] J. V. Guttag, E. Horowitz, and D.Musser. The Design of Data TypeSpecifications, volume IV of Current trends inprogramming methodology, pages 60-79.Prentice-Hall, 1978. Data Structuring. R.T. Yeh(ed.). [GM78] H. Gallaire and J. Minker. Logic andDatabases. Plenum Publishing, 1978. [GM84] J. A. Goguen and J. Meseguer.Equality, Types, Modules and (why not?)Generics for Logic Programming. Journal ofLogic Programming, 1:179-210, 1984. [GMM+78] M. Gordon, R. Milner, L. Morris,M. Ne- wey, and C. Wadsworth. AMetalanguage for Interactive Proof in LCF. In5th ACM Symp. on Principles of ProgrammingLanguages, pages 119-130. ACM, 1978. [GMN84] H. Gallaire, J. Minker, and J. M.Nicolas. Logic and Databases: A DeductiveApproach. Computing Surveys, 16:153-185,1984. [GR83] A. Goldberg and D. Robson. Smalltalk80: The Language and Its Implementation.Addison-Wesley, 1983. [GTW78] J. A. Goguen, J. W. Thatcher, and E.G. Wagner. An Initial Algebra Approach to theSpecification, Correctness and Implementationof Abstract Data Types, volume IV of Currenttrends in programming methodology, chapter 5,pages 80-149. Prentice-Hall, 1978. DataStructuring. R.T. Yeh (ed.). [GTWW76] J. A. Goguen, J. W. Thatcher, E. G.Wagner, and J. B. Wright. A Junction BetweenComputer Science and Category Theory. Part I:IBM Research Report RC 4526. Part II: IBMResearch Report RC 5908, 1973/76. [Gut75] J. V. Guttag. The Specification andApplication to Programming of Abstract DataTypes. Ph.D. thesis. Univ. of Toronto. Dep. ofComputer Science. Report CSRG-59, 1975. [Han72] P. Brinch Hansen. StructuredMultiprogramming. Comm. ACM, 15(7):574-578, July 1972. [Han73] P. Brinch Hansen. ConcurrentProgramming Concepts. Computing Surveys,3(4):223-245, December 1973. [Han75] P. Brinch Hansen. The ProgrammingLanguage Concurrent Pascal. IEEE Trans. onSoftware Engineering, SE-l(2):199-206, June1975. [Han76] P. Brinch Hansen. The SOLOOperating System: Processes, Monitors and Classes.Software Practice and Experience, 6:151-164,1976.

Page 35: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

25

[Han77] P. Brinch Hansen. The Arquitecture ofConcurrent Programs. Prentice Hall, 1977. [Han78] P. Brinch Hansen. DistributedProcesses: A Concurrent Programming Concept.Comm. ACM, 21(11):934-941, November 1978.

[Has95] Report on the Programming LanguageHaskell. Version 1.3. FTP anónimo aftp.dcs.gla.ac.uk//pub/haskell, June 1995. [Hen88] M. Hennessy. Algebraic Theory ofProcesses. MIT Press, London, 1988.

[HF92] P. Hudak and J. H. Fasel. A GentleIntroduction to Haskell. ACM SIGPLANNotices, 27(5), Ma.y 1992.

[Hil74] R. Hill. LUSH Resolution and itsCompleteness. Technical Report DCL-78,School on Artificial Intelligence, Univ. ofEdinburgh, 1974.

[HJF85] C. A. R. Hoare and H. Ji-Feng.Algebraic Specification and Proof of Propertiesof Communicating Sequential Processes.Technical Report PRG-52, Oxford UniversityComputing Laboratory, London, 1985. [HO80] G. Huet and D. Oppen. Equations andRewrite Rules: A Survey. In FormalLanguages: Perspectives and Open Problems.Academic Press, 1980. [Hoa68] C. A. R. Hoare. Record Handling. InProgramming Languages, pages 291-347.Academic Press, 1968. F. Genuys (editor). [Hoa69] C. A. R. Hoare. An Axiomatic Basisfor Computer Programming. Comm. ACM,12(10):89-100,1969. [Hoa72a] C. A. R. Hoare. Notes on DataStructuring. In Structured Programming, pages83-174. Academic Press, 1972. ver [DHD72]. [Hoa72b] C. A. R. Hoare. Proof of Correctnessof Data Representations. Acta Informatica,1:271- 281,1912. [Hoa72c] C. A. R. Hoare. Towards a Theory ofParallel Programming. In Operating SystemsTechniques. Academic Press, 1972. C. A. R.Hoare and R. H. Perrott (editors). [Hoa74] C. A. R. Hoare. Monitors: AnOperating System Structuring Concept. Comm.ACM, 17(10):549-557, October 1974. [Hoa78] C. A. R. Hoare. CommunicatingSequential Processes. Comm. ACM, 21:666-677,1978. [Hoa81] C. A. R. Hoare. The Emperor's OldClothes. Comm. ACM, 24:75-83, 1981. [Hoa84] C. A. R. Hoare. Programming: Sorceryor Science? IEEE Software, pages 5-16, April1984. [Hoa85] C. A. R. Hoare. CommunicatingSequential Processes. Prentice-Hall, London,1985.

[HPJW92] P. Hudak, S. Peyton-Jones, and P.Wadler. Report on the Functional ProgrammingLanguage Haskell. version 1.2. ACM SIGPLANNotices, 27(5), May 1992.

[HS90] E. Horowitz and S. Sahni.Fundamentals of Data Structures in PASCAL.Computer Science Press, 3rd edition, 1990. [Hud93] P. Hudak. Mutable Abstract DataTypes -or- How to Have your State and MungeIt Too. Technical Report RR-914, Dep. ofComputer Science, Yale University, 1993. [Hug90] J. Hughes. Why FunctionalProgramming Matters, pages 17-43. ResearchTopis in Functional Programming. Addison-Wesley, 1990. (Ed.) D. A. Turner. [HW73] C. A. R. Hoare and N. Wirth. AnAxiomatic Definition of the ProgrammingLanguage PASCAL. Acta Informatica, 2:335-355, 1973. [HW88] P. Hudak and P. Wadler. Report on theFunctional Programming Language Haskell.Technical Report RR-656, Yale University.Dep. of Computer Science, 1988. [IBM57] Programmer's Prime for FORTRANAutomatic Coding System for IBM 704. NewYork, IBM Corporation, Form No. 32-03306,1957. [JF89] H. Ji-Feng. Process Simulation andRefinement. Formal Aspects of Computíng,1:229- 241,1989. [JL87] J. Jaffar and J. L. Lassez. ConstraintLogic Programming. In Principles ofProgramming Languages, ACM Press, pages111- 119,1987. [JW74] K. Jensen and N. Wirth. Pascal: UserManual and Report. Springer Verlag, 1974. [Kay93] A. Kay. The Early History ofSmalltalk. SIGPLAN Notices, 23(3):69-95,March 1993.

[KK71] R. A. Kowalski and D. Kuehner. LinearResolution with Selection Function. ArtificialIntelligence, 2:227-260, 1971.

[Kow72] R. A. Kowalski. The PredicateCalculus as a Programming Language. In Int.Symp. and Summer School on MathematicalFoundations of Computer Science, 1972. [Kow79] R. A. Kowalski. Algorithm = Logic + Control. Comm .ACM, 22(7):424-436, July1979. [Kow88] R. A. Kowalski. The Early Years ofLogic Programming. Comm. ACM, 31(1):38-43,January 1988. [KR78] B. W. Kernighan and D. M. Ritchie.The C Programming Language. Prentice-Hall,1978. [Lam77] L. Lamport. Proving the Correctnessof Multiprocess Programs. IEEE Trans. on

Page 36: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

26

Software Engineering, SE-3(2):125-143, March1977.

[Lam80] L. Lamport. The "Hoare" Logic ofConcurrent Programs. Acta Informatica, 14:21-37, 1980. [Lam94] L. Lamport. Temporal Logic ofActions. ACM TOPLAS, 16(3):872-923, May1994.

[Lan65] P. Landin. A Correspondence betweenALGOL 60 and Church Lambda Notation.Comm. ACM, 8:89-101,158-165, 1965.

[Lan66] P. Landin. The Next 700 ProgrammingLanguages. Comm. ACM, 9(3):157-163, March1966.

[Lau93] J. Launchbury. Lazy ImperativeProgramming. In ACM SIGPLAN Workshop onState in Programming Languages, June 1993.

[Les83] P. Lescanne. Computer Experimentswith the REVE Term Rewriting SystemsGenerator. Proc. 10th ACM Conf. on Principlesof Programming Languages, pages 99-108,January 1983. [LG86] B. H. Liskov and J. Guttag. Abstractionand Specification in Software Development.MIT Press, 1986. [Lis72] B. H. Liskov. A Design Methodologyfor Reliable Software Systems. In Fall JointComputer Conference, pages 191-199, 1972. [Lis79] B. H. Liskov. Modular ProgramConstruction Using Abstraction, pages 354-389.LNCS 86. Springer Verlag, 1979.

[LR80] B. W. Lampson and D. D. Redell.Experiences with Processes and Monitors inMESA. Comm. ACM, 23(2):105-117, February1980.

[LS84] L. Lamport and S. B. Schneider. The“Hoare” logic of CSP and all that. ACMTOPLAS, 6(2):281-296, April 1984.

[LSAS77] B. H. Liskov, A. Snyder, R.Atkinson, and C. Schaffert. AbstractionMechanisms in CLU. Comm. ACM, 20(8):564-576, August 1977.

[LW69] P. Luca.s and K. Walk. On the formaldescription of PL/I. Annual Review onAutomatic Programming, 6:105-182, 1969.

[LZ74] B. H. Liskov and S.N. Zilles.Programming with Abstract Data Types. ACMSIGPLAN Notices, 9(4):50-60, 1974. [LZ75] B. H. Liskov and S. N. Zilles.Specification Techniques for Data Abstraction.IEEE Trans. on Software Engineering, SE-l(1):7- 18, March 1975.

[MAE+62] J. McCarthy, P. W. Abrahams, D.Edwards, T. Hart, and M. Levin. LISP 1.5Programmer’s, Manual. MIT Press, Cambridge,Mas- sachusetts, 1962.

[Man91] A. V. Mantsivoda. FLANG: aFunctional Logic Language. In Workshop onProcessing Declarative Klowledge, pages 257-270. Springer Verlag, LNAI 567, 1991. [Mar86] J. J. Martin. Data Types and DataStructures. Prentice-Hall, 1986. [McC62] J. McCarthy. Towards a MathematicalScience of Computation. In Proc. IFIPCongress, 1962. [McC78] J. McCarthy. History of LISP.SIGPLAN Notices, 13:217-223, 1978. [Mey88] B. Meyer. Object-Oriented SoftwareConstruction. Prentice-Hall, 1988. [Mey92] B. Meyer. Eiffel: The Language.Prentice- Hall, 1992. [Mil78] R. Milner. A Theory of TypePolymorphism in Programming. Journal ofComputing Systems Science, 17(3):348-375,1978. [Mi180] R. Milner. A Calcululus ofCommunicating Systems, volume 92 of LectureNotes in Computer Science. Springer- Verlag,Berlin, 1980. [Mi184] R. Milner. A Proposal for StandardML. In Proceedings of the ACM Conf. on Lispand Functional Programming, pages 184-197,1984. [Mil89] R. Milner. Communication andConcurrency. Prentice-Hall, London, 1989. [MM82] A. Martelli and U. Montanari. AnEfficient Unification Allgorithm. ACMTOPLAS, 4(2):258-282, April 1982.

[MMS79] G. J. Mitchell, W. Maybury, and R.Sweet. MESA Language Manual. TechnicalReport CSL- 79-3, Xerox Palo Alto ResearchCenter, 1979. [MNRA89] J. J. Moreno-Navarro and M.Rodriguez- Artalejo. BABEL: A Functional andLogic Programming Language Based onConstructor Discipline, and Narrowing. In Conf.on Algebraic and Logic Programming, pages223-232. Springer Verlag, LNCS 343, 1989. [Mog89] E. Moggi. Computational LambdaCalculus and Monads. In Logics in ComputerScience. IEEE, 1989. [Mor73] J. B. Morris. Types are not Sets. InActas ACM Symposium on Principles ofProgramming Languages, 1973. [MP92] Z. Manna and A. Pnueli. The TemporalLogic of Reactive and Concurrent Systems.Springer- Verlag, 1992.

[MY80] T. W. Mao and R. T. Yeh.Communication Port: A Language Concept for

Page 37: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

27

Concurrent Programming. IEEE Trans. onSoftware Engineering, SE-6(2):194-204, March1980.

[Nau60] Report on tbe Algorithmic LanguageALGOL 60. Comm. ACM, 3(5):299-314, May1960. P. Naur et als. (editors). [Nau63] Revised Report on the AlgorithmicLanguage ALGOL 60. Comm. ACM, 6(1):1-17,Ja- nuary 1963. P. Naur et als. (editors). [Nau66] P. Naur. Proof of Algorithms byGeneral Snapshots. BIT, 6:310-316, 1966. [NHN78] R. Nakajima, M. Honda, and H.Nakahara. Describing and Verifying Programswith Abstract Data Types. In FormalDescription of Programming Concepts. NorthHolland, 1978. [NPP95] M. Núñez, P. Palao, and R. Peña. ASecond Year Course on Data Structures basedon Functional Programming. In LNCS 1022,pages 65-84. Springer- Verlag, 1995. FPLE'95,Nijmegen (The Netherlands). [Occ84] Occam Programming Manual. PrenticeHall, 1984. [OG76] S. S. Owicki and D. Gries. VerifyingProperties of Parallel Programs: An AxiomaticApproach. Comm. ACM, 19(5):279-285, May1976. [OL82] S. S. Owicki and L. Lamport. ProvingLiveness Properties of Concurrent Programs.ACM TOPLAS, 4(3):455-495, July 1982. [ONS92] F. Orejas, M. Navarro, and A.Sánchez. Implementation and BehaviouralEquivalence: A Survey, volume 665 of LNCS,pages 93-125. Springer-Verlag, 1992. 8thWorkshop on Specifications of Abstract DataTypes. 3rd COMPASS Workshop. [Owi75] S. S. Owicki. Axiomatic ProofTechniques for Parallel Programs. TechnicalReport TR- 75-251. Doctoral Dissertation, Dep.Computer Sience, Cornell University, 1975. [Par72a] D. L. Parnas. On the Criteria to beused in Decomposing Systems into Modules.Comm. ACM, 15(12):1053-1058, December1972. [Par72b] D. L. Parnas. A Technique forSoftware Module Specification with Examples.Comm. ACM, 15(5):330-336, May 1972. [Par74] D. L. Parnas. On a "Buzzword":Hierarchical Structure. In IFIP Proceedings,pages 336-339,1974. [Par81] D. Park. Concurrency and Automata onInfinite Sequences. In E. H. L. Aarts, J. vanLeeuwen, and M. Rem, editors, Proceedings 5thGI Conf. of Theoretical Computer Science,volume LNCS 104, pages 245-251. Springer-Verlag, 1981. [PJW93] S. L. Peyton-Jones and P. Wadler.Imperative Functional Programming. In ACM

Symp. on Principles of ProgrammingLanguages, pages 71-84, 1993.

[PN84] L. M. Pereira and R. Nasr. Delta-Prolog:A Distributed Logic Programming Language. InInt. Conf. on Fifth Generation ComputerSystems, pages 283-291, 1984. [Pnu77] A. Pnueli. The Temporal Logic ofPrograms. In 18th Symp. on the Foundations ofComputer Science, pages 46-57, November1977. [RBP+91] J. Rumbaugh, M. Blaha, W.Premerlani, F. Eddy, and W. Lorensen. Object-Oriented Modeling and Design. Prentice-Hall,1991. [Rob65] J. A. Robinson. A Machine-OrientedLogic Based on the Resolution Principle.Journal of the ACM, 12:23-41, Januuy 1965. [RS82] J. A. Robinson and E. E. Sibert.LOGLISP - An Alternative to PROLOG.Machine Intelligence, 10:399-419, 1982. [SF89] G. Springer and D. P. Friedman. Schemeand the Art of Programming. MIT Press, 1989. [Sha83] E. Shapiro. A Subset of ConcurrentProlog and its Interpreter. Technical Report TR-003, ICOT Institute for New GenerationComputer Technology, Tokyo, 1983. [SS71] D. S. Scott and C. Strachey. Towards aMathematical Semantics for ComputerLanguages. In Symp. on Computers andAutomata. Polytechnic Institute of BrooklynPress, pages 19-46, 1971. [Str86a] B. Stroustrup. The C++ ProgrammingLanguage. Addison-Wesley, 1986. [Str86b] B. Stroustrup. An Overview of C++.SIGPLAN Notices, 21(10):7-18, October 1986. [Tur36] A. M. Turing. On Computable Numberswith an Application to theEntscheidungsproblem. Proceedings of theLondon Mathematical Society, 42:230-265,1936. [Tur37] A. M. Turing. Computability and λ-definability. Journal on Symbolic Logic, 2:153-163, 1937. [Tur76] D. A. Turner. SASL Language Manual.Te- chnical Report. University of ST. Andrew.,1976. [Tur81] D. A. Turner. The Semantic Eleganceof Aplicative Languages. In 1981 Conf. onFunctional Programming and ComputerArchitecture, pages 85-92, 1981. [Tur85] D. A. Turner. Miranda: A Non-StrictFunctional Language with Polymorphic Types,pages 1-16. LNCS 201. Springer-Verlag, Berlin,1985. [Tur86] D. A. Turner. An Overview of Miranda.ACM SIGPLAN Notices, 21(12):158- 166, Dec.1986.

Page 38: Lenguajes de programación: Motivación 3º Ingeniería ......Evolución histórica de la programación de computadores Ricardo Peña Marí Profesor Titular de Lenguajes y Sistemas

28

[vEK76] M. H. van Emdem and R. A.Kowalski. The Semantics of Predicate Logics asa Programming Language. Comm. ACM,23(4):733-742, October 1976.

[Wad92] P. Wadler. The Essence of FunctionalProgramming. 19th Symp. on Principles ofProgramming Languages, January 1992. [War77] D. H. D. Warren. Implementing Prolog- Compiling Logic Programs. Technical Report30 and 40, Univ. of Edinburgh, 1977. [WB79] J. Welsh and D. W. Bustard. Pascal-Plus- Another Language for ModularMultiprogramming. Software Practice andExperience, 9:947-957,1979. [WB89] P. L. Wadler and S. Blot. How to Makead-hoc Polymorphism less ad-hoc. In Proc 16thACM Symposium on Principles of ProgrammingLanguage, Austin Texas, pages 60-76, 1989. [Weg72] P. Wegner. The Vienna DefinitionLanguage. Computing Surveys, 4:5-63, March1972. [Wij69] Report on the Algorithmic LanguageALGOL 68. Numerishe Mathematik, 14(2):79-218, February 1969. A. Van Wijngaarden(editor). [Wir66] N. Wirth. A Contribution to theDevelopment of ALGOL. Comm. ACM,9(6):413- 431, June 1966. [Wir71a] N. Wirth. Program Development byStepwise Refinement. Comm. ACM, 14(4):221-227, April 1971. [Wir71b] N. Wirth. The ProgrammingLanguage PASCAL. Acta Informatica, 1:35-73,1971. [Wir77] N. Wirth. Modula: A Language forModular Multiprogramming. Software Practiceand Experience, 7:3-35, July 1977. [Wir82] N. Wirth. Programming in Modula-2. Springer-Verlag, 1982. [Wir88] N. Wirth. The Programming LanguageOberon. Software Practice and Experience,18:671-690,1988. [Wir90] M. Wirsing. Algebraic Specification. InJ. van Leeuwen, editor, Handbook ofTheoretical Computer Science. North Holland,1990.

[WLS76] W. A. Wulf, R. London, and M.Shaw. An Introduction to the Construction andVerification of ALPHARD Programs. IEEETrans. on Software Engineering, SE-2:253-264,1976.

[WPP79] D. H. D. Warren, F. Pereira, and L. M.Pereira. User's Guide to DECsystem-10 Prolog.Technical Report 15, Dep. of ArtificialIntelligence, Univ. of Edinburgh, 1979.