Lenguajes de Programación

 

Al desarrollarse las primeras computadoras electrónicas, se vio la necesidad de programarlas, es decir, de almacenar en memoria la información sobre la tarea que iban a ejecutar. Las primeras se usaban como calculadoras simples; se les indicaban los pasos de cálculo, uno por uno.

John Von Neumann desarrolló el modelo que lleva su nombre, para describir este concepto de "programa almacenado". En este modelo, se tiene una abstracción de la memoria como un conjunto de celdas, que almacenan simplemente números. Estos números pueden representar dos cosas: los datos, sobre los que va a trabajar el programa; o bien, el programa en sí.

¿Cómo es que describimos un programa como números? Se tenía el problema de representar las acciones que iba a realizar la computadora, y que la memoria, al estar compuesta por switches correspondientes al concepto de bit, solamente nos permitía almacenar números binarios.

La solución que se tomó fue la siguiente: a cada acción que sea capaz de realizar nuestra computadora, asociarle un número, que será su código de operación (opcode) . Por ejemplo, una calculadora programable simple podría asignar los opcodes :

1 = SUMA, 2 = RESTA, 3 = MULTIPLICA, 4 = DIVIDE.

Supongamos que queremos realizar la operación 5 * 3 + 2, en la calculadora descrita arriba. En memoria, podríamos "escribir" el programa de la siguiente forma:

Localidad Opcode Significado Comentario 0 5 5 En esta localidad, tenemos el primer número de la fórmula 1 3 * En esta localidad, tenemos el opcode que representa la multiplicación. 2 3 3 En esta localidad, tenemos el segundo número de la fórmula 3 1 + En esta localidad, tenemos el opcode que representa la suma. 4 2 2 En esta localidad, tenemos el último número de la fórmula

Podemos ver que con esta representación, es simple expresar las operaciones de las que es capaz el hardware (en este caso, nuestra calculadora imaginaria), en la memoria.

La descripción y uso de los opcodes es lo que llamamos lenguaje de máquina . Es decir, la lista de códigos que la máquina va a interpretar como instrucciones, describe las capacidades de programación que tenemos de ella; es el lenguaje más primitivo, depende directamente del hardware, y requiere del programador que conozca el funcionamiento de la máquina al más bajo nivel.

los lenguajes más primitivos fueron los lenguajes de máquina. Esto, ya que el hardware se desarrolló antes del software, y además cualquier software finalmente tiene que expresarse en el lenguaje que maneja el hardware.

La programación en esos momentos era sumamente tediosa, pues el programador tenía que "bajarse" al nivel de la máquina y decirle, paso a pasito, cada punto de la tarea que tenía que realizar. Además, debía expresarlo en forma numérica; y por supuesto, este proceso era propenso a errores, con lo que la productividad del programador era muy limitada. Sin embargo, hay que recordar que en estos momentos, simplemente aún no existía alternativa.

La programación consiste en desarrollar programas para procesar información.

programación como termino se utiliza para designar la creacion de programas a pequeña escala, el desarrollo de sistemas complejos se denomina ingenieria de software.

Una computadora es totalmente inutil si no dispone de un programa capaz de procesar información.
Para que se realize dicho procesamiento de información habra sido necesario construir un ordenador (hardware), pensar y crear un programa (software) y ejecutar dicho programa o aplicacion en el computador.
La ultima de estas fases es la que realiza el usuario, las anteriores son realizadas por tecnicos que construyen el hardware y por programadores que desarrollan el software.

programación e ingenieria de software son complementarias entre si. Para el desarrollo de grandes sistemas informaticos se divide el trabajo en tareas que diversos programadores desarrollaran. Al terminar se unen las piezas como en un puzzle para completar el sistema en si. Asi programación tambien se aplica para el desarrollo de grandes sistemas en las ingenierias de software.

La programación tiene como objetivo el tratamiento de la información correctamente, con lo que se espera que un programa de el resultado correcto y no uno erroneo. Asi que cada aplicacion debe funcionar segun lo esperado en terminos de programación.

Otro objetivo fundamental de la programación es que sean de codigos claros y legibles, con lo que si un programador inicia un programa y no lo termina, otro programador sea capaz de entender la codificacion y poder terminarlo.
Normalmente en programación existen ciertas normas no escritas de como han de nombrarse los componentes, objetos o controles de cada sistema, asi como sus variables que deben ser relativas al termino al cual se van a vincular. Por ejemplo el texto que contenga la edad del individuo se llamaria TxtEdad, y su variable se llamaria Edad.

Por ultimo la programación pretende que sus programas sean utiles y eficientes.
De multitud de maneras la programación nos dara el mismo resultado de un programa, un buen programador llegara al mismo resultado con un minimo de codigo y de la forma más clara y logica posible.

De los anteriormente nombrados objetivos de la programación el más importante es el de la correccion, ya que un codigo claro y legible facilita el mantenimiento de la aplicacion o sistema.

Un computador no hará nada si no se le dan órdenes. Estas pueden ser tipeadas directamente en el teclado pero, salvo que la tarea sea muy sencilla -como hacer alguna operación aritmética-, sería muy ineficiente, por lo cual se requiere redactar primero un programa, con la serie completa de instrucciones para que la máquina realice lo que deseamos. Pero si hablamos tanto de "tipear" órdenes directas como de agruparlas en un programa, estamos hablando de usar un teclado parecido al de una máquina de escribir, con letras, cifras y signos. Ha de usarse, por lo tanto, un determinado lenguaje... ¡que el computador, originalmente, no entiende!
 
 

COMO NACE UNA APLICACION

Todas las "aplicaciones" (software para el "usuario final") que conocemos han debido ser creadas especificando primero sus funciones y traduciendo éstas en "instrucciones" comprensibles por la máquina.
Para ésto, el o los programadores utilizan un determinado "lenguaje de programación", que es como un idioma: cuenta con un diccionario (los "comandos") y una gramática (reglas de sintaxis). El programador traduce las especificaciones de funciones y operaciones (que están en su idioma natural y/o en gráficos que especifican su secuencia) en este idioma, elaborando un producto llamado "programa fuente".
Este programa fuente ha de ser luego traducido (por el mismo computador) en el "lenguaje de máquina", que es el que "entiende" el microprocesador. La traducción, por lo tanto, debe hacerse teniendo en cuenta el "lenguaje" propio del chip procesador (de ahí que un mismo programa tendrá una versión "para PowerPC (PPC)", "para Pentium", etc.
Esta traducción puede hacerse de dos maneras: en forma previa al uso, con lo cual se genera el "programa compilado" o "programa objeto", o bien se instala junto con el programa de traducción en el computador del usuario y se hace que la máquina traduzca las órdenes a medida que lee el programa fuente.
A diferencia de un programa interpretado, un programa compilado (como la mayoría de las aplicaciones que hoy puede comprar el usuario común) sólo puede ser utilizado, pero no puede ser leído, revisado o modificado: la compilación lo hace ilegible. Tratar de "decompilarlo" para conocer su estructura y modo de funcionar (lo cual se llama "reverse engineering") es muy complejo y normalmente prohibido en las condiciones de venta. Así, la versión "fuente" constituye un "secreto comercial", celosamente guardado por los fabricantes. Veremos, al final del capítulo, que este secreto puede ser algunas veces perjudicial para los usuarios.

El primer gran avance que se dio, como ya se comentó, fue la abstracción dada por el Lenguaje Ensamblador, y con él, el nacimiento de las primeras herramientas automáticas para generar el código máquina. Esto redujo los errores triviales, como podía ser el número que correspondía a una operación, que son sumamente engorrosos y difíciles de detectar, pero fáciles de cometer. Sin embargo, aún aquí es fácil para el programador perderse y cometer errores de lógica, pues debe bajar al nivel de la forma en que trabaja el CPU, y entender bien todo lo que sucede dentro de él.

Con el desarrollo en los 50s y 60s de algoritmos de más elevado nivel, y el aumento de poder del hardware, empezaron a entrar al uso de computadoras científicos de otras ramas; ellos conocían mucho de Física, Química y otras ramas similares, pero no de Computación, y por supuesto, les era sumamente complicado trabajar con lenguaje Ensamblador en vez de fórmulas. Así, nació el concepto de Lenguaje de Alto Nivel, con el primer compilador de FORTRAN (FORmula TRANslation), que, como su nombre indica, inició como un "simple" esfuerzo de traducir un lenguaje de fórmulas, al lenguaje ensamblador y por consiguiente al lenguaje de máquina. A partir de FORTRAN, se han desarrollado innumerables lenguajes, que siguen el mismo concepto: buscar la mayor abstracción posible, y facilitar la vida al programador, aumentando la productividad, encargándose los compiladores o intérpretes de traducir el lenguaje de alto nivel, al lenguaje de computadora.

Hay que notar la existencia de lenguajes que combinan características de los de alto nivel y los de bajo nivel (es decir, Ensamblador). Mi ejemplo favorito es C: contiene estructuras de programación de alto nivel, y la facilidad de usar librerías que también son características de alto nivel; sin embargo, fue diseñado con muy pocas instrucciones, las cuales son sumamente sencillas, fáciles de traducir al lenguaje de la máquina; y requiere de un entendimiento apropiado de cómo funciona la máquina, el uso de la memoria, etcétera. Por ello, muchas personas consideramos a lenguajes como C (que fue diseñado para hacer sistemas operativos), lenguajes de nivel medio.

 Las tendencias en los lenguajes de programación

 

El estudio de los lenguajes de programación agrupa tres intereses diferentes; el del programador profesional, el del diseñador del lenguaje y del Implementador del lenguaje.

Además, estos tres trabajos han de realizarse dentro de las ligaduras y capacidades de la organización de una computadora y de las limitaciones fundamentales de la propia "calculabilidad". El termino "el programador" es un tanto amorfo, en el sentido de que camufla importantes diferencias entre distintos niveles y aplicaciones de la programación. Claramente el programador que ha realizado un curso de doce semanas en COBOL y luego entra en el campo del procesamiento de datos es diferente del programador que escribe un compilador en Pascal, o del programador que diseña un experimento de inteligencia artificial en LISP, o del programador que combina sus rutinas de FORTRAN para resolver un problema de ingeniería complejo, o del programador que desarrolla un sistema operativo multiprocesador en ADA.

En esta investigación, intentaremos clarificar estas distinciones tratando diferentes lenguajes de programación en el contexto de cada área de aplicación diferente. El "diseñador del lenguaje" es también un termino algo nebuloso. Algunos lenguajes (como APL y LISP) fueron diseñados por una sola persona con un concepto único, mientras que otros (FORTRAN y COBOL) son el producto de desarrollo de varios años realizados por comités de diseño de lenguajes.

El "Implementador del lenguaje" es la persona o grupo que desarrolla un compilador o interprete para un lenguaje sobre una maquina particular o tipos de maquinas. Mas frecuentemente, el primer compilador para el lenguaje Y sobre la maquina X es desarrollada por la corporación que manufactura la maquina X . Por ejemplo, hay varios compiladores de Fortran en uso; uno desarrollado por IBM para una maquina IBM, otro desarrollado por DEC para una maquina DEC, otro por CDC, y así sucesivamente. Las compañías de software también desarrollan compiladores y también lo hacen los grupos de investigación de las universidades. Por ejemplo, la universidad de Waterloo desarrolla compiladores para FORTRAN Y PASCAL, los cuales son útiles en un entorno de programación de estudiantes debido a su superior capacidad de diagnostico y velocidad de compilación.

Hay también muchos aspectos compartidos entre los programadores, diseñadores de un lenguaje implementadores del mismo. Cada uno debe comprender las necesidades y ligaduras que gobiernan las actividades de los otros dos.

Hay, al menos, dos formas fundamentales desde las que pueden verse o clasificarse los lenguajes de programación: por su nivel y por principales aplicaciones. Además, estas visiones están condicionadas por la visión histórica por la que ha transcurrido el lenguaje. Además, hay cuatro niveles distintos de lenguaje de programación.

 

Los "Lenguajes Declarativos" son los mas parecidos al castellano o ingles en su potencia expresiva y funcionalidad están en el nivel mas alto respecto a los otros. Son fundamentalmente lenguajes de ordenes, dominados por sentencias que expresan "Lo que hay que hacer" en ves de "Como hacerlo". Ejemplos de estos lenguajes son los lenguajes estadísticos como SAS y SPSS y los lenguajes de búsqueda en base de datos, como NATURAL e IMS. Estos lenguajes se desarrollaron con la idea de que los profesionales pudieran asimilar mas rápidamente el lenguaje y usarlo en su trabajo, sin necesidad de programadores o practicas de programación.

Los lenguajes de " Alto Nivel" son los mas utilizados como lenguaje de programación. Aunque no son fundamentalmente declarativos, estos lenguajes permiten que los algoritmos se expresen en un nivel y estilo de escritura fácilmente legible y comprensible por otros programadores. Además, los lenguajes de alto nivel tienen normalmente las características de " Transportabilidad". Es decir, están implementadas sobre varias maquinas de forma que un programa puede ser fácilmente " Transportado " (Transferido) de una maquina a otra sin una revisión sustancial. En ese sentido se llama "Independientes de la maquina". Ejemplos de estos lenguajes de alto nivel son PASCAL , APL y FORTRAN (para aplicaciones científicas ), COBOL (para aplicaciones de procesamiento de datos), SNOBOL( para aplicaciones de procesamiento de textos), LISP y PROLOG (para aplicaciones de inteligencia artificial), C y ADA (para aplicaciones de programación de sistemas) y PL/I (para aplicaciones de propósitos generales) .

Los "Lenguajes Ensambladores" y los "Lenguajes Maquina" son dependientes de la maquina. Cada tipo de maquina, tal como VAX de digital, tiene su propio lenguaje maquina distinto y su lenguaje ensamblador asociado. El lenguaje Ensamblador es simplemente una representación simbólica del lenguaje maquina asociado, lo cual permite una programación menos tediosa que con el anterior. Sin embargo, es necesario un conocimiento de la arquitectura mecánica subyacente para realizar una programación efectiva en cualquiera de estos niveles lenguajes.

Los siguiente tres segmentos del programa equivalentes exponen las distinciones básicas entre lenguajes maquina, ensambladores de alto nivel:

Como muestra este ejemplo, a mas bajo nivel de lenguaje mas cerca esta de las características de un tipo e maquina particular y mas alejado de ser comprendido por un humano ordinario. Hay también una estrecha relación ( correspondencia 1:1 ) entre las sentencias en lenguaje ensamblador y sus formas en lenguaje maquina codificada. La principal diferencia aquí es que los lenguajes ensambladores se utilizan símbolos (X,Y,Z,A para " sumar", M para "multiplicar"), mientras que se requieren códigos numéricos (OC1A4, etc.) para que lo comprenda la maquina.

La programación de un lenguaje de alto nivel o en un lenguaje ensamblador requiere, por tanto, algún tipo de interfaz con el lenguaje maquina para que el programa pueda ejecutarse. Las tres interfaces mas comunes: un "ensamblador" , un "compilador" y un "interprete". El ensamblador y el compilador traduce el programa a otro equivalente en el lenguaje X de la maquina "residente" como un paso separado antes de la ejecución. Por otra parte, el interprete ejecuta directamente las instrucciones en un lenguaje Y de alto nivel, sin un paso de procesamiento previo.

La compilación es, en general, un proceso mas eficiente que la interpretación para la mayoría de los tipos de maquina. Esto se debe principalmente a que las sentencias dentro de un "bucle" deben ser reinterpretadas cada vez que se ejecutan por un interprete. Con un compilador. Cada sentencia es interpretada y luego traducida a lenguaje maquina solo una vez.

Algunos lenguajes son lenguajes principalmente interpretados, como APL, PROLOG y LISP. El resto de los lenguajes -- Pascal, FORTRAN, COBOL, PL/I, SNOBOL, C, Ada y Modula-2 – son normalmente lenguajes compilados. En algunos casos, un compilador estará utilizable alternativamente para un lenguaje interpretado (tal como LISP) e inversamente (tal como el interprete SNOBOL4 de los laboratorios Bell). Frecuentemente la interpretación es preferible a la compilación en un entorno de programación experimental o de educación, donde cada nueva ejecución de un programa implicado un cambio en el propio texto del programa. La calidad de diagnosis y depuración que soportan los lenguajes interpretados es generalmente mejor que la de los lenguajes compilados, puesto que los mensajes de error se refieren directamente a sentencias del texto del programa original. Además, la ventaja de la eficiencia que se adjudica tradicionalmente a los lenguajes compilados frente a los interpretados puede pronto ser eliminado, debido a la evolución de las maquinas cuyos lenguajes son ellos mismos1lenguajes de alto nivel. Como ejemplo de estos están las nuevas maquinas LISP, las cuales han sido diseñadas recientemente por Symbolics y Xerox Corporations.

Los lenguajes de Programación son tomados de diferentes perspectivas. Es importante para un programador decidir cuales conceptos emitir o cuales incluir en la programación. Con frecuencia el programador es osado a usar combinaciones de conceptos que hacen al lenguaje "DURO" de usar, de entender e implementar. Cada programador tiene en mente un estilo particular de programación, la decisión de incluir u omitir ciertos tipos de datos que pueden tener una significativa influencia en la forma en que el Lenguaje es usado, la decisión de usar u omitir conceptos de programación o modelos.

Existen cinco estilo de programación y son los siguientes:

1.                  Orientados a Objetos.

2.                Imperativa : Entrada, procesamiento y salidas de Datos.

3.                Funcional : "Funciones", los datos son funciones, los resultados pueden ser un valor o una función.

4.                Lógico : {T,F} + operaciones lógicos (Inteligencia Artificial).

5.                Concurrente : Aún esta en proceso de investigación.

 

El programador, diseñador e implementador de un lenguaje de programación deben comprender la evolución histórica de los lenguajes para poder apreciar por que presentan características diferentes. Por ejemplo, los lenguajes "mas jóvenes" desaconsejan (o prohiben) el uso de las sentencias GOTO como mecanismo de control inferior, y esto es correcto en el contexto de las filosofías actuales de ingeniería del software y programación estructurada. Pero hubo un tiempo en que la GOTO, combinada con la IF, era la única estructura de control disponible; el programador no dispone de algo como la construcción WHILE o un IF-THEN-ELSE para elegir. Por tanto, cuando se ve un lenguaje como FORTRAN, el cual tiene sus raíces en los comienzos de la historia de los lenguajes de programación, uno no debe sorprenderse de ver la antigua sentencia GOTO dentro de su repertorio.

Lo mas importante es que la historia nos permite ver la evolución de familias de lenguajes de programación, ver la influencia que ejercer las arquitecturas y aplicaciones de las computadoras sobre el diseño de lenguajes y evitar futuros defectos de diseño aprendido las lecciones del pasado. Los que estudian se han elegido debido a su mayor influencia y amplio uso entre los programadores, así como por sus distintas características de diseño e implementacion. Colectivamente cubren los aspectos más importantes con los que ha de enfrentarse el diseñado de lenguajes y la mayoría de las aplicaciones con las que se enfrenta el programador. Para los lectores que estén interesados en conocer con mas detalle la historia de los lenguajes de programación recomendamos las actas de una recién conferencia (1981) sobre este tema, editadas por Richard Wexelblat. Vemos que FORTRAN I es un ascendente directo de FORTRAN II, mientras que FORTRAN, COBOL, ALGO 60, LISP, SNOBOL y los lenguajes ensambladores, influyeron en el diseño de PL/I.

También varios lenguajes están prefijados por las letras ANS. Esto significa que el American National Standards Institute ha adoptado esa versión del lenguaje como el estándar nacional. Una vez que un lenguaje esta estandarizado, las maquinas que implementan este lenguaje deben cumplir todas las especificaciones estándares, reforzando así el máximo de transportabilidad de programas de una maquina a otra. La policía federal de no comprar maquinas que no cumplan la versión estándar de cualquier lenguaje que soporte tiende a "fortalecer" el proceso de estandarizacion, puesto que el gobierno es, con mucho, el mayor comprador de computadoras de la nación.

Finalmente, la notación algebraica ordinaria, por ejemplo, influyo fuertemente en el diseño de FORTRAN y ALGOL. Por otra parte, el ingles influyo en el desarrollo del COBOL. El lambda calculo de Church dio los fundamentos de la notación funcional de LISP, mientras que el algoritmo de Markov motivo el estilo de reconocimiento de formas de SNOBOL. La arquitectura de computadoras de Von Neumann, la cual fue una evolución de la maquina mas antigua de Turing, es el modelo básico de la mayoría de los diseños de computadoras de las ultimas tres décadas. Esta maquina no solo influyeron en los primeros lenguajes sino que también suministraron el esqueleto operacional sobre el que evoluciono la mayoría de la programación de sistemas.

Una discusión mas directa de todos estos primeros modelos no están entre los objetivos de este texto. Sin embargo, es importante apuntar aquí debido a su fundamental influencia en la evolución de los primeros lenguajes de programación, por una parte, y por su estado en el núcleo de la teoría de la computadora, por otra. Mas sobre este punto, cualquier algoritmo que pueda describirse en ingles o castellano puede escribirse igualmente como una maquina de Turing (maquina de Von Neumann), un algoritmo de Markov o una función recursiva. Esta sección, conocida ampliamente como "tesis de Church", nos permite escribir algoritmos en distintos estilos de programación (lenguajes) sin sacrificar ninguna medida de generalidad, o potencia de programación, en la transición.

 

La programación orientada a objetos, intenta simular el mundo real a traves del significado de objetos que contiene caracteristicas y funciones. Los lenguajes orientados a objetos se clasifican como lenguajes de quinta generacion.

Como su mismo nombre indica, la programación orientada a objetos se basa en la idea de un objeto, que es una combinacion de variables locales y procedimientos llamados metodos que juntos conforman una entidad de programación.

El termino encapsulacion se usa para describir la combinacion de estructuras de datos y de metodos que son manipulados por el objeto. La llamada a un objeto es lo que se denomina pasar un "aviso" a un objeto.

En la programación orientada a objetos, encapsular significa, reunir y controlar el grupo resultante como un todo y no individualmente.

En la programación orientada a objetos la abstraccion es un termino externo al objeto, que controla la forma en que es visto por los demas.

En la programación orientada a objetos la modularidad se considera de la siguiente manera: Un programa grande siempre sera más complicado que la suma de varios programas pequeños, con lo que se considera ventajoso dividir un gran sistema en diversos modulos.

En la programación orientada a objetos tenemos la jerarquia, la cual consiste en la clasificacion y organizacion de las abstracciones segun su naturaleza. El más claro ejemplo de jerarquia es la herencia.

En la programación orientada a objetos se define la herencia como una jerarquia de extracciones, y la relacion entre clases, donde se comparte la estructura y el comportamiento de una o más clase considerada como clases superiores o una superclase, con lo cual se resume que la herencia es una unidad independiente por si misma heredada de una abstraccion o superclase. Un ejemplo cotidiano lo encontramos en las aplicaciones que existen cactualmente en el mercado, donde un formulario cualquiera hereda las caracteristicas de uan ventana del sistema operativo Windows (Maximizar, Minimizar, Cerrar)

 

LENGUAJES DE BAJO Y ALTO NIVEL

En efecto, lo único que entienden y pueden manipular la Unidad de Control y la Unidad Aritmética son dígitos binarios o sea series de ceros y unos (paso o no paso de corriente eléctrica). Así, mientras el hombre usa un "lenguaje natural" (idioma) muy rico en significados, la máquina usa un sistema en que existiría un sólo "significado": la diferencia entre 0 y 1 (o sea un bit de información).
¿Cómo lograr más? Simplemente concibiendo un nuevo lenguaje constituído de "bloques" de dígitos binarios (llamados "bytes"). Este es el primer paso o "primer nivel" en la construcción de lenguajes de computación.

1er Nivel
Se dice que el código binario es de "bajo nivel" o "primer nivel" (porque al usar pocos signos logra muy dificilmente expresar cosas complicadas), mientras un lenguaje humano es de "muy alto nivel" (con una cantidad mayor de signos y con reglas combinatorias logra expresar con facilidad cosas muy complicadas). Todo el esfuerzo, entonces, para facilitar la comunicación del hombre con el computador, ha de centrarse en el desarrollo de lenguajes de mayor nivel.
El fabricante de un procesador fija los bloques de bits que llevarán a la CPU (unidad central de procesos) a reconocer y realizar diferentes operaciones. Este el el "código de máquina", primer lenguaje que la máquina puede interpretar y transformar en acciones. Pero es evidentemente muy difícil de usar para un ser humano. Supongamos que quiera hacer imprimir y para ello deba decir "10011101 11100010": ¿cómo recordar órdenes de este tipo y no equivocarse al escribirlas?
Practicamente nadie trabaja hoy a este nivel, excepto los diseñadores de "chips" procesadores. Del mismo modo que es posible pasar de un sistema binario a un sistema decimal (más comprensible y más desarrollado en términos de signos legibles) es posible asociar a los bloques de bits no solo valores decimales sino también otros signos. Esto lleva a un segundo nivel de expresión.
Hemos de recordar que el teclado equivale a un conjunto de interruptores: cada tecla que pulsamos equivale a cerrar brevemente uno de éstos, es decir produciendo un bit de información (no teclear = 0, teclear =1). Pero dado que hay muchas teclas, hay que identificar cada una, por lo cual pulsar una tecla significa activar un circuito que generará un "bloque" binario (byte) específico que identifica esa tecla.
A cada tecla está asociado un código decimal y un código hexadecimal. El hexadecimal (16 caracteres: de 0 a 9 y de la A a la F) es el que sirve de intermediario a la máquina, para traducir nuestro código natural (alfanumérico) al código binario. Algunos ejemplos de equivalentes decimales y hexadecimales del teclado son los siguientes:

 

Tecla

Valor Decimal

Valor Hexadecimal

1

49

31

2

50

32

9

57

39

a

97

61

b

98

62

i

105

69

j

106

6A

k

107

6B

o

111

6F

p

112

70

z

122

7A

!

33

21

?

63

3F

=

61

3D

Esto permite no sólo reconocer los signos del teclado y reproducirlos (como en un procesador de palabras), sino también atribuir a cada tecla otra función y hacer -por ejemplo- que transmita una orden a la CPU. Así, podríamos ordenar la impresión con un simple "?", o -como es común hoy en los Macintosh- apretando simultáneamente una tecla de "comando" y la letra "P".

2º Nivel
La creación de un lenguaje más comprensible por el hombre consiste por lo tanto en establecer la equivalencia de bloques binarios con signos de nuestro lenguaje habitual. Para permitir la programación (secuencia de comandos), se usan pequeños conjuntos de signos ("palabras") de fácil memorización, con las cuales se redactan programas, por ejemplo "ADC" significará "sumar con reserva" (en inglés: "ADd with Carry"). Este tipo de lenguaje se llama "ensamblador" o "Assembler" (Vea más adelante la "Descripción" de Lenguajes). La máquina misma hará la tarea de traducirlo en código binario, para seguir las instrucciones, gracias a otro programa cuya función es traducir la expresión humana en "lenguaje de máquina" (binario). Es programa se llama "compilador".
Aunque el Assembler es un inmenso progreso en relación al código binario, su desventaja reside en que permanece estrechamente ligado a los bloques binarios que reconoce la CPU (es decir al "hardware"). Para facilitar más la tarea, se han inventado lenguajes de "alto nivel", es decir más cercanos al modo de expresar del hombre que de operación de la máquina. Los primeros y más comunes son los llamados de "tercera generación", más fáciles de manejar y más independientes de las características técnicas de los procesadores. Ahora, hasta un aficionado puede llegar a redactar un programa, sin tener que preocuparse por el código binario o de ensamble: si un programa traductor podía resolver la transformación de bloques de signos en bloques binarios, era cosa de extender las habilidades del traductor para "enseñar" a la máquina cómo "entender" un lenguaje más complejo y agregar mecanismos automáticos de manejo de la memoria para poder utilizar lenguajes aún más comprensibles.

3er Nivel
El avance en el desarrollo de "compiladores" e "intérpretes" (los dos tipos de programas traductores) ha sido por lo tanto fundamental en el desarrollo de los lenguajes de "3º generación" cuyas ventajas además de la facilidad de aprendizaje y lectura/escritura son las facilidades de corrección, transformación y conversión de un lenguaje a otro.
Los más antiguos son el FORTRAN (para aplicaciones matemáticas y científicas) y el COBOL (para aplicaciones de administración y contabilidad).
 Con los micro-computadores nació el BASIC ("para principiantes"). Mucha importancia tiene el PASCAL, especialmente en la docencia. (Más detalles luego, en la "Descripción" de los lenguajes).

Generadores de aplicaciones o 4º Nivel
Posteriormente, usando estos lenguajes, se han redactado programas destinados a facilitar un número variado de operaciones en campos de aplicación específicos como simulación de fenómenos físicos, manipulación de datos estadísticos, etc. Los más avanzados y flexibles de estos programas son las planillas electrónicas u hojas de cálculo y los programas de administración de archivos o bases de datos (Vea el capítulo "Aplicaciones").
Dados que tales aplicaciones no "hacen nada" sin que el usuario defina ciertas estructuras y ciertas operaciones, pueden ser consideradas como "generadores" de aplicaciones, aunque este nombre se reserva habitualmente para niveles más avanzados en que los usuarios pueden generar sistemas muy diferentes unos de otros, con "herramientas" que se parecen a lenguajes de programación. Estas herramientas conforman los lenguajes de cuarto nivel que son por esencia "programas para crear programas" con una finalidad específica, como el "CASE" destinado a facilitar el trabajo de los analistas de sistemas.
 
 

ESTRUCTURA DE UN LENGUAJE

Todo lenguaje, para permitir la programación, ha de contener diversos tipos de instrucciones:

Instrucciones simples:

·                    de entrada: para buscar y recoger datos en la memoria central o auxiliar, o bien obtenerla por interacción con el usuario (p.ej. mensaje en el monitor de video que debe ser contestado en el teclado),

·                    de salida: datos expuestos en el monitor de video o impresos, o transmitidos en una red,

·                    de asignación: asignar un valor a una variable, sea directamente (p.ej. Variable1 = 15) sea por cálculo (p.ej. Var3 = Var1 + Var2).

Instrucciones compuestas:

·                    de secuencia: por principio el orden dado a las instrucciones determina el orden en que se ejecuten, salvo instrucciones especiales de "salto" como las previstas en instrucciones de alternación o iteración.
Toda instrucción compuesta debe tener una ENTRADA y una SALIDA. Puede siempre reemplazarse una instrucción simple por una compuesta manteniéndose el principio de secuencialidad de las instrucciones.

·                    de alternación: escoger entre dos alternativas en función del cumplimiento de una condición (p.ej. if X > 15 then ... else ...: si X es mayor que 15 haga esto, sino este otro)

·                    de iteración: ejecutar repetidamente un grupo de instrucciones mientras se cumpla una condición (p.ej. para contar de 1 hasta 10: N=1, while N < 10 repeat {N = N+1, print N}. O sea mientras N sea inferior a 10, agregue 1 al valor anterior de N).

En este ejemplo, se introduce un concepto muy importante en el desarrollo y uso de lenguajes de programación: la recursividad, factible por el hecho de que lo que se manipula es siempre un valor colocado en alguna celda de memoria. Así, si bien la matemática no puede aceptar una ecuación como N=N+1, aquí estamos ante una instrucción (no una ecuación) que significa "tomar el valor que está en una celda llamada N, sumarle 1 y volver a colocar el nuevo valor en la celda llamada N. Ésta es una "instrucción de asignación".
Algunos lenguajes (el Algol y sus descendientes como Pascal y "C", y también Lisp y Prolog en que este procedimiento constituye la esencia del lenguaje) van aún más lejos y permiten una recursividad consistente en la posibilidad de que una instrucción compuesta ordene la ejecución de sí misma. El siguiente podría ser una breve ejemplo:
Para imprimir una lista con una instrucción recursiva, basta tener en cuenta que una lista se compone de una cabeza (primer elemento) y una cola (el resto). Obviamente la cola es también una lista, por lo cual se le puede aplicar el procedimiento consistente en separar su cabeza de su cola, y así sucesivamente, hasta encontrar una cola vacía. Por lo tanto, se puede ordenar algo así:

imprimir lista = imprimir cabeza

lista = cola       [borra de la lista la cabeza ya impresa]

si lista no es vacía, imprimir lista    [orden de recursión]

sino: fín.


 

 

PROGRAMACION ESTRUCTURADA

Como explicado a propósito de las "Instrucciones", todo programa se compone de una secuencia de instrucciones que pueden ser simples o compuestas. La presencia de instrucciones que deban repetirse muchas veces no sólo se expresa en las iteraciones, donde dicha repetición es inmediata. Existen muchos casos en que la repetición no es un flujo contínuo sino dependiente de otras operaciones o condiciones que son muy variables. Es el caso por ejemplo de las instrucciones para leer o grabar datos en un disco.
La programación estructurada, que es una forma de redacción de programas (obligatoria u optativa, según el lenguaje escogido), se hace cargo de este requisito facilitando la constitución de "paquetes" de instrucciones (llamados "sub-rutinas" o "procedimientos"), los que pueden escribirse una sola vez y ser "llamados" (utilizados) las veces que se requiera.
Además, pone énfasis en la conveniencia de facilitar la lectura de los programas haciendo más visible la dependencia jerárquica de las instrucciones compuestas mediante "indentación", es decir modificando el ancho del margen izquierdo para cada grupo de instrucciones.
 
 
 

 

 

 

 

SISTEMA OPERATIVO

Los 'SISTEMAS OPERATIVOS" son programas de funcionamiento permanente, no específicos, que deben cargarse en la memoria principal antes de cualquier otro programa o aplicación específica. Son conjuntos de instrucciones que cualquier programa requiere para poder operar, por lo cual era más razonable y económico separarlos (en vez de repetir las mismas instrucciones preliminares en cada programa). Responden tanto a un concepto de modularidad como de eficiencia ya que -al ser independientes- basta que se carguen al encender el computador para luego poder ejecutar varios programas sin necesidad de volver a dar estas instrucciones.
Su objetivo fundamental es "tender un puente" activo entre el hardware y el software encargándose de las funciones de:

1. Interfaz con el usuario:
La interfaz (o forma de interacción) puede ser de tipo intuitivo, como el escritorio, los íconos y las ventanas del Macintosh o de Windows (llamados por ello "entorno de escritorio"), o bien basada en "lenguaje de comandos" como en DOS,

2. Administración de la CPU y la memoria principal:
Crea subdivisiones en la RAM, indicando dónde deben colocarse las instrucciones, los datos originales y los que generen los programas. En algunos casos puede hacer que sólo una parte de un programa o de los datos sea "cargada" -y reemplazada en el momento oportuno-, para economizar espacio y trabajar con un conjunto de información mayor que el que cabe en la RAM (caso común de las bases de datos). (En este caso se habla del uso de "memoria virtual").

3. Administración de la memoria auxiliar:
Determina la longitud de los "paquetes" de datos que leen desde o envían a los dispositivos de memoria auxiliar, la forma y el lugar físico en que se guardan, la forma de acceder a ellos (construyen el "directorio" o índice de los discos, por ejemplo).
Para todas estas funciones, el sistema operativo reconoce ciertas instrucciones que forman parte del lenguaje de alto nivel (p.ej. "open", "read", "write", "save", etc.) y genera para cada una múltiples instrucciones en lenguaje de máquina de tal modo que el procesador efectúe todas las operaciones requeridas.
Los sistemas operativos también determinan la forma en que se codifican las instrucciones y los datos que provienen del teclado. Todos los sistemas de origen americano hoy usan el  ASCII (American Standard Code for Information Interchange), que tenía originalmente 128 caracteres (suficiente para el inglés). Pero esta cantidad impedía el uso de varios signos, entre ellos los acentos. Por ello se usa hoy el "Ascii extendido", que cuenta con 256 caracteres. Pero en la segunda serie de 128 caracteres, los diferentes sistemas operativos han recurrido a opciones diferentes y no son compatibles entre sí (razón por la cual los textos acentuados se ven con caracteres extraños cuando se pasa de un tipo de computador a otro, como del Macintosh al PC).
Es también la razón por la cual, en el correo electrónico, conviene escribir sin acentos (usando el ASCII reducido), para asegurar un texto más legible.

Sistemas operativos de computadores personales
Los sistemas operativos hoy más difundidos en los computadores personales (PC) son dos:

·                    el DOS (Disk Operating System), para los PC llamados "IBM compatibles", que utilizan principalmente chips procesadores Intel (como los Pentium),

·                    el MacOS (Macintosh Operating System), para los Apple Macintosh, que utilizan chips procesadores Motorola (como los PowerPC).

El DOS, nacido a fines de los años setenta, ya tiene numerosas versiones, que han tenido que introducir numerosos "parches" para poder administrar la cantidad de memoria de que hoy se dispone (en RAM y en disco) y en la cual no se soñaba en la época de su creación. Originalmente destinado a expertos, ha tenido que ser complementado con una interfaz gráfica -de la cual no disponía-, conocida como "Windows". Dada la gran libertad de manejo de las instrucciones básicas, las aplicaciones variaban mucho en la manera en que presentaban al usuario las opciones de trabajo (ventanas, comandos, etc.), hasta que "Windows 95" se impuso como estándar para las aplicaciones finales en PC-DOS.
El MacOS fue concebido desde el inicio (1984) como un sistema basado en metáforas visuales y orientado al tratamiento de información gráfica, lo cual facilita enormemente la interacción humana. También se ha caracterizado por la coherencia de todas las aplicaciones que funcionan con él. Siempre se respeta el mismo diseño y manejo de las ventanas, la estructura de los menus y posición de los comandos en éstos, etc. lo cual hace muy fácil aprender a usar aplicaciones nuevas y pasar de una a otra. El MacOS es además capaz de leer datos generados en "PC compatibles" y guardados en diskettes de formato DOS (aunque no todos los formatos de datos, ya que éstos dependen de las aplicaciones que los crearon): su diskettera es más "compatible" que la de los otros PC. Las máquinas más potentes también pueden ser cargadas con una aplicación especial ("SoftPC" o "SoftWindows") para utilizar programas hechos para el DOS.
En el futuro es probable que estas diferencias desaparezcan, ya que se está trabajando en un sistema operativo más universal y en aplicaciones que funcionen cualquiera sea el sistema operativo (gracias, por ejemplo, al lenguaje "Java").
Importancia creciente está tomando el sistema operativo "Linux", que es un sistema derivado del Unix (sistema operativo de "mainframes" y estaciones de trabajo) y destinado a los computadores personales (con versiones para los procesadores Intel y Motorola-PPC). Su principal ventaja es que su código fuente es "abierto", es decir de conocimiento público, a diferencia de los códigos-fuente de los MacOS, DOS y Windows, que sólo se entregan compilados. De este modo, cualquier programador capacitado puede revisar, mejorar o ajustar a sus propias necesidades su propio Linux, mientras esto es imposible con MacOS y DOS/Windows. Incluso los programadores de aplicaciones finales deben contar con licencias especiales de los fabricantes (Apple y Microsoft) para poder conocer las funciones incluídas en estos sistemas operativos, lo cual da a dichos fabricantes un poder de control que puede ser excesivo (razón, en parte, de los juicios contra Microsoft). . En efecto, es posible incluir en el sistema operativo funciones no reveladas, lo cual permite a su fabricante desarrollar aplicaciones finales que funcionan mejor que las de sus competidores, o incluso que impiden que éstas tengan acceso al procesador o que fallen reiteradas veces (lo cual facilita una competencia desleal). Por todo ello crece un importante movimiento en favor de los sistemas y aplicaciones "libres" (es decir de código fuente "abierto", o sea público, lo cual no quiere decir "gratis").
 
 
 

 

 

 

RESUMEN DE LENGUAJES DE PROGRAMACION MAS COMUNES

ADA
Es un lenguaje estructurado parecido al PASCAL, destinado a controlar mecanismos en "tiempo real" (o sea una velocidad compatible con las necesidades reales), pero de gran complejidad. Admite una programación "orientada a objetos" y un sistema de alta modularidad de tipo hipertexto.
Fue elaborado a pedido del Departamento de Defensa de los Estados Unidos y establecido como norma para todos los fabricantes que participaban en el programa de la Iniciativa de Defensa Estratégica (IDE, también llamado "Guerra de las Galaxias").
 
 

ASSEMBLER (ENSAMBLADOR)
Como señalado a propósito del "Primer Nivel" de los lenguajes, el Assembler es directamente dependiente de los circuitos electrónicos de los procesadores (que constituyen el núcleo de los computadores), por lo cual escribir en Ensamblador sigue siendo una tarea muy compleja, a lo cual hay que sumar que el código varía de un procesador a otro aunque existe ya un jerga común para ciertas operaciones como las aritméticas y lógicas, por ejemplo:

ADD para sumar (sin reserva) ADC para sumar con reserva ("add with carry") MUL para multiplicar ORA para el "o" lógico ("or and") EOR para el "o" exclusivo (o bien... o bien...)

Las instrucciones de este tipo deben ir seguidas sea de dos valores (dos números a sumar o multiplicar por ejemplo) o del nombre de una variable. Cuando se ejecute el programa, el valor de una variable nombrada deberá provenir de una operación anterior que

·                    haya terminado por una instrucción del tipo "almacenar el resultado del operación en la variable X",

·                    haya extraído el valor de la variable de una determinada celda de memoria, o

·                    haya efectuado una interacción con el usuario, por ejemplo escribir en pantalla "Escriba el valor de X".

(Estas son "instrucciones de asignación").
El Assembler contiene además un conjunto mínimo de instrucciones de alternación e iteración indispensables para que un programa pueda funcionar como tal.

Cuando abstraemos los opcodes y los sustituimos por una palabra que sea una clave de su significado, a la cual comúnmente se le conoce como mnemónico , tenemos el concepto de Lenguaje Ensamblador . Así, podemos definir simplemente al Lenguaje Ensamblador de la siguiente forma:

Lenguaje Ensamblador es la primera abstracción del Lenguaje de Máquina , consistente en asociar a los opcodes palabras clave que faciliten su uso por parte del programador

Como se puede ver, el Lenguaje Ensamblador es directamente traducible al Lenguaje de Máquina, y viceversa; simplemente, es una abstracción que facilita su uso para los seres humanos. Por otro lado, la computadora no entiende directamente al Lenguaje Ensamblador; es necesario traducirle a Lenguaje de Máquina. Originalmente, este proceso se hacía a mano, usando para ello hojas donde se escribían tablas de programa similares al ejemplo de la calculadora que vimos arriba . Pero, al ser tan directa la traducción, pronto aparecieron los programas Ensambladores, que son traductores que convierten el código fuente (en Lenguaje Ensamblador) a código objeto (es decir, a Lenguaje de Máquina).

Una característica que hay que resaltar, es que al depender estos lenguajes del hardware, hay un distinto Lenguaje de Máquina (y, por consiguiente, un distinto Lenguaje Ensamblador) para cada CPU. Por ejemplo, podemos mencionar tres lenguajes completamente diferentes, que sin embargo vienen de la aplicación de los conceptos anteriores:

1.Lenguaje Ensamblador de la familia Intel 80x86 2.Lenguaje Ensamblador de la familia Motorola 68000 3.Lenguaje Ensamblador del procesador POWER, usado en las IBM RS/6000.

Tenemos 3 fabricantes distintos, compitiendo entre sí y cada uno aplicando conceptos distintos en la manufactura de sus procesadores, su arquitectura y programación; todos estos aspectos, influyen en que el lenguaje de máquina y ensamblador cambie bastante.

Ventajas y desventajas del Lenguaje Ensamblador

Una vez que hemos visto la evolución de los lenguajes, cabe preguntarse: ¿En estos tiempos "modernos", para qué quiero el Lenguaje Ensamblador?

El proceso de evolución trajo consigo algunas desventajas, que ahora veremos como las ventajas de usar el Lenguaje Ensamblador, respecto a un lenguaje de alto nivel:

1.Velocidad

2.Eficiencia de tamaño

3.Flexibilidad

Por otro lado, al ser un lenguaje más primitivo, el Ensamblador tiene ciertas desventajas respecto a los lenguajes de alto nivel:

1.Tiempo de programación 2.Programas fuente grandes 3.Peligro de afectar recursos inesperadamente 4.Falta de portabilidad

Velocidad

El proceso de traducción que realizan los intérpretes, implica un proceso de cómputo adicional al que el programador quiere realizar. Por ello, nos encontraremos con que un intérprete es siempre más lento que realizar la misma acción en Lenguaje Ensamblador, simplemente porque tiene el costo adicional de estar traduciendo el programa, cada vez que lo ejecutamos.

De ahí nacieron los compiladores, que son mucho más rápidos que los intérpretes, pues hacen la traducción una vez y dejan el código objeto, que ya es Lenguaje de Máquina, y se puede ejecutar muy rápidamente. Aunque el proceso de traducción es más complejo y costoso que el de ensamblar un programa, normalmente podemos despreciarlo, contra las ventajas de codificar el programa más rápidamente.

Sin embargo, la mayor parte de las veces, el código generado por un compilador es menos eficiente que el código equivalente que un programador escribiría. La razón es que el compilador no tiene tanta inteligencia, y requiere ser capaz de crear código genérico, que sirva tanto para un programa como para otro; en cambio, un programador humano puede aprovechar las características específicas del problema, reduciendo la generalidad pero al mismo tiempo, no desperdicia ninguna instrucción, no hace ningún proceso que no sea necesario.

Para darnos una idea, en una PC, y suponiendo que todos son buenos programadores, un programa para ordenar una lista tardará cerca de 20 veces más en Visual Basic (un intérprete), y 2 veces más en C (un compilador), que el equivalente en Ensamblador.

Por ello, cuando es crítica la velocidad del programa, Ensamblador se vuelve un candidato lógico como lenguaje.

Ahora bien, esto no es un absoluto; un programa bien hecho en C puede ser muchas veces más rápido que un programa mal hecho en Ensamblador; sigue siendo sumamente importante la elección apropiada de algoritmos y estructuras de datos. Por ello, se recomienda buscar optimizar primero estos aspectos, en el lenguaje que se desee, y solamente usar Ensamblador cuando se requiere más optimización y no se puede lograr por estos medios.

Tamaño

Por las mismas razones que vimos en el aspecto de velocidad, los compiladores e intérpretes generan más código máquina del necesario; por ello, el programa ejecutable crece. Así, cuando es importante reducir el tamaño del ejecutable, mejorando el uso de la memoria y teniendo también beneficios en velocidad, puede convenir usar el lenguaje Ensamblador. Entre los programas que es crítico el uso mínimo de memoria, tenemos a los virus y manejadores de dispositivos (drivers). Muchos de ellos, por supuesto, están escritos en lenguaje Ensamblador.

Flexibilidad

Las razones anteriores son cuestión de grado: podemos hacer las cosas en otro lenguaje, pero queremos hacerlas más eficientemente. Pero todos los lenguajes de alto nivel tienen limitantes en el control; al hacer abstracciones, limitan su propia capacidad. Es decir, existen tareas que la máquina puede hacer, pero que un lenguaje de alto nivel no permite. Por ejemplo, en Visual Basic no es posible cambiar la resolución del monitor a medio programa; es una limitante, impuesta por la abstracción del GUI Windows. En cambio, en ensamblador es sumamente sencillo, pues tenemos el acceso directo al hardware del monitor.

Resumiendo, la flexibilidad consiste en reconocer el hecho de que

Todo lo que puede hacerse con una máquina, puede hacerse en el lenguaje ensamblador de esta máquina; los lenguajes de alto nivel tienen en una u otra forma limitantes para explotar al máximo los recursos de la máquina.

Tiempo de programación

Al ser de bajo nivel, el Lenguaje Ensamblador requiere más instrucciones para realizar el mismo proceso, en comparación con un lenguaje de alto nivel. Por otro lado, requiere de más cuidado por parte del programador, pues es propenso a que los errores de lógica se reflejen más fuertemente en la ejecución.

Por todo esto, es más lento el desarrollo de programas comparables en Lenguaje Ensamblador que en un lenguaje de alto nivel, pues el programador goza de una menor abstracción.

Programas fuente grandes

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

Peligro de afectar recursos inesperadamente

Tenemos la ventaja de que todo lo que se puede hacer en la máquina, se puede hacer con el Lenguaje Ensamblador (flexibilidad). El problema es que todo error que podamos cometer, o todo riesgo que podamos tener, podemos tenerlo también en este Lenguaje. Dicho de otra forma, tener mucho poder es útil pero también es peligroso.

En la vida práctica, afortunadamente no ocurre mucho; sin embargo, al programar en este lenguaje verán que es mucho más común que la máquina se "cuelgue", "bloquee" o "se le vaya el avión"; y que se reinicialize. ¿Por qué?, porque con este lenguaje es perfectamente posible (y sencillo) realizar secuencias de instrucciones inválidas, que normalmente no aparecen al usar un lenguaje de alto nivel.

En ciertos casos extremos, puede llegarse a sobreescribir información del CMOS de la máquina (no he visto efectos más riesgosos); pero, si no la conservamos, esto puede causar que dejemos de "ver" el disco duro, junto con toda su información.

Falta de portabilidad

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

 

 

ALGOL
El ALGOL ("ALGOrithmic Lenguage") es el primer lenguaje que fue creado por un comité internacional. En 1960 se reunieron representantes de varios países europeos y de Estados Unidos para crear un lenguaje destinado a "describir procesos" mediante instrucciones de control (iteraciones y alternaciones) de nivel más elevado que las existentes en las versiones existentes de su predecesor, el FORTRAN.
Permite escribir programas de resolución de problemas en forma limpia y clara, de fácil lectura. Aunque poco "transportable" (no permite con facilidad que un programa escrito para un tipo de computador funcione en otro), es de gran importancia conceptual por cuanto introdujo la "programación estructurada", lo cual influyó en muchos lenguajes creados posteriormente.
En 1968 se implementó una nueva versión multi-propósito especialmente orientada a la tercera generación de computadores que empezaban a copar el mercado. (A diferencia de la primera versión, ésta resultó muy compleja y, por ello, tuvo poco éxito).

EJEMPLO:

REAL PROCEDURE exp(x);

VALUE x; REAL x;

BEGIN

        REAL sum, term, n;

        sum:= 1; term:= 1; n:= 0;

        FOR n:= n+1 WHILE abs (term) > 0.001 DO

        BEGIN

                term:= x * term / n;

                sum:= sum + term

        END;

        exp:= sum

END.

BASIC
El BASIC ("Beginner's All-purpose Symbolic Instruction Code")nació con los microcomputadores, como un lenguaje simplificado y multi-propósito destinado a los usuarios no-especialistas.
Permite resolver problemas numéricos o comerciales así como crear y mantener archivos, realizar gráficos lineales, etc. Es por esencia un lenguaje interpretado y no-estructurado. Sin embargo, existen algunos compiladores, pero no es común recurrir a ellos. Y también es factible redactar los programas en forma estructurada.

EJEMPLO

10   INPUT A

20   INPUT B

30   C = A+ B

40   IF C > 100 THEN 90

50   PRINT "Suma = "; C

60   PRINT

70   PRINT "Desea seguir? "; : GET R$

80   IF R$ = "S" THEN 10

90   PRINT "Resultado superior a 100!"

100 END

QBasic

Qbasic es un lenguaje de alto nivel, el cual consiste en instrucciones que los humanos pueden relacionar y entender. El compilador de Qbasic se encarga de traducir el mismo a lenguaje de máquina.

Un programa es una secuencia de instrucciones. El proceso de ejecutar esas instrucciones se llama correr el programa. Los programas contienen las funciones de entrada, procesamiento y salida. La persona que resuelve problemas mediante escribir programas en la computadora se conoce como programador. Después de analizar el problema y desarrollar un plan para solucionarlo, escribe y prueba el programa que instruye a la computadora como llevar a cabo el plan. El procedimiento que realiza el programador se define como "problem solving". Pero es necesario especificar que un programador y un usuario no son lo mismo. Un usuario es cualquier persona que use el programa.

Ejemplo de qbasic, para hacer una calculadora

DIM total AS DOUBLE

DIM number AS DOUBLE

DIM secondNumber AS DOUBLE

DIM more AS STRING

DIM moreNumbers AS STRING

DIM operation AS STRING

total = 0

more = "y"

moreNumbers = "c"

CLS

WHILE more = "y"

INPUT "Enter the first number"; number

total = number

WHILE moreNumbers = "c"

COLOR 14

PRINT "The total is:"; total

COLOR 7

PRINT "Select an operation"

COLOR 2

PRINT "(+)"

COLOR 5

PRINT "(-)"

COLOR 1

PRINT "(x)"

COLOR 4

INPUT "(/)"; operation

COLOR 7

CLS

IF operation = "+" THEN

REM where we do additions

PRINT "Enter the number to Add to"; total

INPUT secondNumber

total = secondNumber + total

COLOR 14

PRINT "The total is now:"; total

COLOR 7

ELSE

IF operation = "-" THEN

REM subtraction

PRINT "Enter the number to Subtract from"; total

INPUT secondNumber

total = total - secondNumber

COLOR 14

PRINT "The total is now:"; total

COLOR 7

ELSE

IF operation = "x" THEN

REM multiplication

PRINT "Enter the number to Multiply"; total; "by"

INPUT secondNumber

total = secondNumber * total

REM * is the multiplication sign in programs

COLOR 14

PRINT "The total is now:"; total

COLOR 7

ELSE

IF operation = "/" THEN

REM division

PRINT "Enter the number to Divide"; total; "by"

INPUT secondNumber

IF secondNumber = 0 THEN

COLOR 4

PRINT "You cannot divide by zero"

COLOR 7

ELSE

total = total / secondNumber

REM / is the division sign in programs

END IF

COLOR 14

PRINT "The total is now:"; total

COLOR 7

ELSE

PRINT "you must select an operation"

END IF

END IF

END IF

END IF

INPUT "Do you wish to continue (c) or start with new numbers

(n)";moreNumbers

CLS

WEND

COLOR 14

PRINT "The grand total is:"; total

COLOR 7

INPUT "Do you wish to make more calculations (y - n)"; more

moreNumbers = "c"

REM if we don't put "moreNumbers" back to y, it will always

REM come back to "Do you wish to make more calculations" and never REM ask

for numbers again

REM (try it)

total = 0

REM if we don't reset the total to 0, it will just

REM keep on adding to the total

WEND

END


 

C y C++
El lenguaje "C" es bastante reciente y está especialmente orientado hacia el desarrollo de software de sistemas operativos y utilitarios que anteriormente se escribían en Assembler. Se usa hoy como base para crear el software que funciona con el sistema operativo "UNIX", logrando un alto grado de portabilidad, es decir de independencia respecto de los procesadores (con lo cual es fácil lograr que un mismo programa pueda ser ejecutado en diferentes modelos de computadores).
El "C++" es un lenguaje desarrollado a partir del "C" pero con una estructura "orientada a objetos", lo cual facilita un mejor manejo de datos.
 
 
 

C

C es un lenguaje de programación diseñado por Dennis Ritchie, de los Laboratorios Bell, y

se instaló en un PDP-11 en 1972; se diseñó para ser el lenguaje de los Sistemas Operativos

UNIX1. A su vez, UNIX es un Sistema Operativo desarrollado por Ken Thompson, quién

utilizó el lenguaje ensamblador y un lenguaje llamado B para producir las versiones originales de UNIX, en 1970. C se inventó para superar las limitaciones de B.

C es un lenguaje maduro de propósitos generales que se desarrolló a partir de estas raíces;

su definición aparece en 1978 en el apéndice ``C Reference Manual'' del libro The C

Programming Language, de Brian W. Kernighan y Dennis M. Ritchie (Englewood Cliffs,

Nueva Jersey, Prentice-Hall 1978), pero el estándar recomendable más reciente apareció en

junio de 1983, en el documento de los Laboratorios Bell titulado The C Programming

Language-Reference Manual, escrito por Dennis M. Ritchie

Un programa en C

Generalizando, un programa en C consta de tres secciones. La primera sección es donde van todos los ``headers''. Estos ``headers'' son comúnmente los ``#define'' y los ``#include''. Como segunda sección se tienen las ``funciones''. Al igual que Pascal, en C todas las funciones que se van a ocupar en el programa deben ir antes que la función principal (main()). Declarando las funciones a ocupar al principio del programa, se logra que la función principal esté antes que el resto de las funciones. Ahora, solo se habla de funciones ya que en C no existen los procedimientos.

Y como última sección se tiene a la función principal, llamada main. Cuando se ejecuta el programa, lo primero que se ejecuta es esta función, y de ahí sigue el resto del programa.

Los símbolos { y } indican ``begin'' y ``end'' respectivamente. Si en una función o en un ciclo while, por ejemplo, su contenido es de solamente una línea, no es necesario usar ``llaves'' ({ }), en caso contrario es obligación usarlos.

Ejemplo de un programa en C

/*Programa ejemplo que despliega el contenido de "ROL" en pantalla*/

#include <stdio.h>

#define ROL "9274002-1"

despliega_rol() {

printf("Mi rol es : \%s\n", ROL);

}

void main() {

despliega_rol();

}

/* Fin programa */

 

COBOL
EL COBOL ("COmmon Business-Oriented Language") es uno de los primeros lenguajes de programación creados. Fue desarrollado en 1960 por CODASYL (Conference on Data Systems Languages), un comité en que participaron fabricantes y usarios, a pedido de la Marina de los Estados Unidos. Este comité estuvo dirigido por la Dra. Grace Hopper, una de las primeras programadoras de la computadora ENIAC. Es uno de los pocos lenguajes reconocidos como norma internacional (americana por el ANSI -American National Standards Institute- y europea por el ISO -International Organization for Standardization-).
Está orientado -como su nombre indica- a aplicaciones comerciales, por lo cual sus instrucciones están especialmente diseñadas para facilitar la entrada y salida de datos (impresión de tablas, etc.). Se pretendió que se pareciera lo más posible a un lenguaje natural, por lo cual requiere mucho más escritura que otros lenguajes. Esto facilita la lectura posterior pero resulta aburrido para los redactores. Debe iniciarse con secciones donde se declaran todas las variables y los periféricos que se van a usar, cosas que muchos lenguajes posteriores ya no requieren.
Los programas escritos en COBOL, que es un lenguaje compilado, se clasifican en cuatro divisiones: Identification, Enviroment, Data y Procedure. La Identification division especifica el nombre del programa y contiene información general del programa como puede ser su autor, fecha en que se escribió y una pequeña descripción de su utilidad, así como cualquier otra documentación que el programador desee añadir.
La Enviroment division especifica qué equipo o equipos se están utilizando, y los archivos empleados en el programa para la entrada y la salida.
La Data division describe los datos utilizados en el programa.
La Procedure division contiene la parte del procesamiento que dicta las acciones del programa.

EJEMPLO

IDENTIFICATION DIVISION.

PROGRAM-ID. SUMA.

 

ENVIRONMENT DIVISION.

INPUT-OUTPUT SECTION.

FILE-CONTROL.

  SELECT ENTRADA ASSIGN TO INPUT.

  SELECT SALIDA ASSIGN TO OUTPUT.

 

DATA DIVISION.

FILE SECTION.

FD ENTRADA LABEL RECORD IS OMITTED.

   01 VENTA.

   02 VALOR PICTURE 9999V99.

   03 FILLER PICTURE X(44).

FD SALIDA LABEL RECORD IS OMITTED.

   01 RESULTADOS PICTURE X(132).

WORKING STORAGE SECTION.

...

PROCEDURE DIVISION.

...

FORTRAN
El FORTRAN ("FORmula TRANslator") fue desarrollado entre los años 1954 y 1957 por un equipo dirigido por James Backus, fue el primer lenguaje compilado e inclusive hoy en día es usado ampliamente en la solución de problemas numéricos. Aunque fue el más común hasta 1970, sigue siendo de primera importancia en aplicaciones científicas por cuanto se adapta muy bien a la forma tradicional de escribir fórmulas matemáticas. Al contrario, no se presta con facilidad al manejo de archivos y produccción de tablas de resultados.
Existen numerosas versiones y perfeccionamientos posteriores. (La versión de 1966 fue instituída como estándar por el Instituto Americano de Estandarización, reemplazándola por el FORTRAN 77 en la década siguiente).

EJEMPLO

      INTEGER A, B, C

  10  READ (5,1010) A, B

1010  FORMAT (I4,I4)

          C = A - B

          IF (C. EQ. 0) GO TO 20

          WRITE (6,1020) C

1020  FORMAT (I4)

          GO TO 10

  20  STOP

      END

HYPERTALK
"HyperTalk" es el lenguaje desarrollado por Dan Winkler para Bill Atkinson, el creador del "HyperCard" para Apple-Macintosh. Está orientado a la creación de aplicaciones conforme al sistema de "hiperarchivos" (sistemas de fichas interrelacionadas donde se facilita el "navegar" de un archivo a otro).
HyperTalk es un buen ejemplo de lenguaje orientado a objetos. Este tipo de lenguaje combina la lógica declarativa con los algoritmos (Vea "PROLOG"). Un programa ya no es una secuencia de instrucciones sino un conjunto de objetos agrupados en conjuntos, definidos mediante atributos y a los cuales pueden asociarse instrucciones. Así, en HyperCard, existen archivos ("stacks" o "pilas") que agrupan fichas ("cards"), y cada una de éstas contiene campos de datos y botones. Todos son "objetos" que -si bien mantienen entre sí una relación jerárquica- tienen asociados paquetes de instrucciones ("scripts") independientes unos de otros. Cada objeto pertenece a un conjunto (como fichas o botones) que tiene "atributos" propios comunes a todos sus miembros, y cada atributo tendrá un valor común o específico para cada caso. Para dar o buscar dicho valor intervienen "facetas" que son instrucciones (procedimientos) asociadas.
 
 

HTML
El HTML o "HyperText Marking Language" es el lenguaje que se utiliza para crear páginas -como la presente- en World Wide Web.
El HTML se basa en los mismos principios que el HyperTalk, permitiendo definir segmentos (de texto o ilustraciones) que remiten a otros, facilitando una "navegación" por múltiples vías, a gusto del usuario. Así es como el botón "Home" tiene asociadas las instrucciones que indican al procesador que busque la primera ficha o página del archivo llamado "Home" o "index" en el archivo del computador que presta el servicio de conexión (servidor). Y si se hace un clic en una palabra subrayada, se pasa a ver otra sección del mismo documento o algún otro documento (otro "objeto").
El HTML no es propiamente un lenguaje de programación , sino solo de exhibición de contenidos y navegación, porque no define operaciones.
 

JAVA
JAVA es un lenguaje de programación basado en el C++ (con cambios en la sintaxis y nuevas restricciones de codificación). Permite agregar animaciones y puntos sensibles en páginas de texto. Aunque se lo pretende presentar como "EL" lenguaje destinado a desarrollos para World Wide Web, es mucho mas complejo que el HTML e incluso que otros lenguajes utilizables por los browsers (navegadores) de la Web.
Una versión muy reducida es el "JavaScript", que se puede combinar con el lenguaje HTML, dentro de una página web.

El lenguaje de programación Java, fue diseñado por la compañía Sun Microsystems Inc, con el propósito de crear un lenguaje que pudiera funcionar en redes computacionales heterogéneas ( redes de computadoras formadas por más de un tipo de computadora, ya sean PC, MAC's, estaciones de trabajo, etc.),y que fuera independiente de la plataforma en la que se vaya a ejecutar. Esto significa que un programa de Java puede ejecutarse en cualquier máquina o plataforma. El lenguaje fue diseñado con las siguientes características en mente:

·                    Simple. Elimina la complejidad de los lenguajes como "C" y da paso al contexto de los lenguajes modernos orientados a objetos. Orientado a Objetos. La filosofía de programación orientada a objetos es diferente a la programación convencional.

·                    Familiar. Como la mayoría de los programadores están acostumbrados a programar en C o en C++, el sintaxis de Java es muy similar al de estos.

·                    Robusto. El sistema de Java maneja la memoria de la computadora por ti. No te tienes que preocupar por apuntadores, memoria que no se esté utilizando, etc. Java realiza todo esto sin necesidad de que uno se lo indique.

·                    Seguro. El sistema de Java tiene ciertas políticas que evitan se puedan codificar virus con este lenguaje. Existen muchas restricciones, especialmente para los applets, que limitan lo que se puede y no puede hacer con los recursos críticos de una computadora.

·                    Portable. Como el código compilado de Java (conocido como byte code) es interpretado, un programa compilado de Java puede ser utilizado por cualquier computadora que tenga implementado el interprete de Java.

·                    Independiente a la arquitectura. Al compilar un programa en Java, el código resultante un tipo de código binario conocido como byte code. Este códido es interpretado por diferentes computadoras de igual manera, solamente hay que implementar un intérprete para cada plataforma. De esa manera Java logra ser un lenguaje que no depende de una arquitectura computacional definida.

·                    Multithreaded. Un lenguaje que soporta multiples threads es un lenguaje que puede ejecutar diferentes líneas de código al mismo tiempo.

·                    Interpretado. Java corre en máquina virtual, por lo tanto es interpretado.

·                    Dinámico. Java no requiere que compiles todas las clases de un programa para que este funcione. Si realizas una modificación a una clase Java se encarga de realizar un Dynamic Bynding o un Dynamic Loading para encontrar las clases.

Java puede funcionar como una aplicación sola o como un "applet", que es un pequeño programa hecho en Java. Los applets de Java se pueden "pegar" a una página de Web (HTML), y con esto puedes tener un programa que cualquier persona que tenga un browser compatible podrá usar.

Nota:Diferencia entre Java y CGI La diferencia es esencialmente simple, un CGI se ejecuta en el servidor mientras que un programa en Java se ejecuta en la máquina del usuario.

Java funciona de la siguiente manera: El compilador de Java deja el programa en un Pseudo-código (no es código maquinal) y luego el intérprete de Java ejecuta el programa (lo que se conoce como el "Java Virtual Machine"). Por eso Java es multiplataforma, existe un intérprete para cada máquina diferente. Nota: El código maquinal es el código binario que la computadora entiende y puede ejecutar.

Para entender bien como funciona un applet de Java vean el siguiente ejemplo:

1.                  Existe un código de Java en un servidor de Web. (Los códigos de Java se caracterizan por tener la extensión *.class).

2.                Una persona en Internet, con un browser compatible con Java, realiza una conección al servidor.

3.                El servidor envía el documento HTML y el código en Java (*.class).

4.                En la computadora del usuario remoto llegan ambos, y la Máquina Virtual de Java, que está en el browser, transforma el código Java en un código que entienda la máquina local y se ejecuta el programa dentro de la página de Web.

5.                Si el usuario realiza otra conexión a otro URL o se sale del browser, el programa se deja de ejecutar y en la computadora no queda rastro de el.

 

 

Ejemplo de tutorial de Java:

En Java hay tres tipos de comentarios:

// comentarios para una sola línea

/* comentarios de una o

más líneas

*/

/** comentario de documentación, de una o más líneas

*/

Los dos primeros tipos de comentarios son los que todo programador conoce y se utilizan del mismo modo. Los comentarios de documentación, colocados inmediatamente antes de una declaración (de variable o función), indican que ese comentario ha de ser colocado en la documentación que se genera automáticamente cuando se utiliza la herramienta de Java, javadoc. Dichos comentarios sirven como descripción del elemento declarado permitiendo generar una documentación de nuestras clases escrita al mismo tiempo que se genera el código.

En este tipo de comentario para documentación, se permite la introducción de algunos tokens o palabras clave, que harán que la información que les sigue aparezca de forma diferente al resto en la documentación.

Identificadores

Los identificadores nombran variables, funciones, clases y objetos; cualquier cosa que el programador necesite identificar o usar.

En Java, un identificador comienza con una letra, un subrayado (_) o un símbolo de dólar ($). Los siguientes caracteres pueden ser letras o dígitos. Se distinguen las mayúsculas de las minúsculas y no hay longitud máxima.

 

Serían identificadores válidos:

identificador

nombre_usuario

Nombre_Usuario

_variable_del_sistema

$transaccion

y su uso sería, por ejemplo:

int contador_principal;

char _lista_de_ficheros;

float $cantidad_en_Ptas;

Unix

Ejemplo de Unix:

No todo el "árbol" de directorios está compuesto por directorios de usuario. Existen muchos de ellos que son de uso general o del propio sistema y con los que habrá que familiarizarse. Los más importantes son:

/

El raíz, del que "cuelgan" todos.

/bin y /usr/bin

Contienen comandos UNIX ejecutables.

/etc

Es quizá el directorio más importante. Contiene ficheros de datos y configuración del sistema, el fichero de password, configuración de terminales, red, etc (de ahí su nombre).

/dev

Ficheros de dispositivos E/S.

/usr/man

Manual

/tmp

Directorio para arreglos temporales. TODOS los usuarios pueden leer y escribir en él.


 
 

LISP
LISP ("LIst Processing Language") es un lenguaje computacional bastante diferente de los demás. Es un lenguaje funcional, es decir que acumula informaciones e instrucciones bajo la apariencia de fórmulas (como en álgebra). Estas informaciones toman la forma de listas (de ahí su nombre), que son memorizadas y comparadas para efectuar luego operaciones que consisten en "evaluar las fórmulas". El conjunto de funciones constituye el programa en cuanto la evaluación de una función llama a otra y así sucesivamente (en forma eminentemente recursiva). El control de la ejecución depende del intérprete (que busca la secuencia y la traduce en lenguaje máquina), mientras depende del programador la forma en que las funciones se llaman entre sí.
El objetivo de este tipo de lenguaje es asemejarse a una forma humana de conservación de información (la de las descripciones) y permitir la construcción de programas que se enriquezcan o ajusten en función del uso (simulando aprendizaje). Así, LISP es el primer lenguaje creado con el fín de ser una herramienta para el desarrollo de la inteligencia artificial.

EJEMPLO

? (de append (L1 L2)

       (if (null L1)

       L2

       (cons (cor L1)

              (append (cdr L1) L2))))


 

LOGO
Creado por Seymour Papert, padre de la "computación educativa", el LOGO está destinado a la enseñanza de la programación a los niños, desde temprana edad. Por ello es sobretodo conocido por su capacidad gráfica y su "tortuga", que es el puntero con el cual se realizan los dibujos. Es altamento modular y deja gran libertad al usuario para definir procedimientos desde muy simples hasta muy complejos, en forma jerárquica, permitiendo incluso el control de periféricos mecánicos (operación de pequeños robots). Aunque bastante poderoso (se han escrito procesadores de palabras en LOGO), practicamente no es utilizado fuera de la escuela básica.

EJEMPLO

Comandos para dibujar un cuadrado de 20 pixels (puntos) por lado:
BAJAR_PLUMA. ADELANTE 20. ROTACION 90. ADELANTE 20. ROTACION 90. ADELANTE 20. ROTACION 90. ADELANTE 20. LEVANTAR_PLUMA.

Lo que conforma el cuadrado puede simplificarse como: HACER 4 (ADELANTE 20. ROTACION 90). y ser utilizado repetidamente definiendo el comando "Cuadrado":
>CUADRADO: HACER 4 (ADELANTE 20. ROTACION 90).

Esta definición se puede generalizar reemplazando la longitud por una variable (El programa pide automáticamente en pantalla el valor de una variable si lo desconoce): >CUADRADO: HACER 4 (ADELANTE LADO. ROTACION 90).

(Las órdenes para bajar y levantar la "pluma" -que permiten dejar o no dejar rastro al mover la "tortuga" - pueden introducirse o no en la definición, a voluntad).


 

PASCAL
Del nombre del filosófico y matemático francés, PASCAL es un lenguaje inicialmente diseñado para la docencia introductoria de la programación (a nivel superior). Surgió alrededor de 1970, en gran parte como reacción simplificadora después de la creación de los muy complejos PL/1 y ALGOL68 para los nuevos computadores de tercera generación.
Muy inspirado en la primera versión oficial de ALGOL (60), es un lenguaje muy estructurado y con alta modularidad. Tuvo por ello -y por su simplicidad- mucha aceptación al punto de ser utilizado para crear importantes aplicaciones e incluso compiladores y sistemas operativos (antes desarrollados en Assembler).

EJEMPLO

PROGRAM CALCULATOR;

   VAR

      A, B: INTEGER;

      OPERATION; CHAR;

BEGIN

   REPEAT

      READLN (A, OPERATION, B);

      IF OPERATION = '+' THEN

         WRITELN (A + B)

      ELSE IF OPERATION = '-' THEN

         WRITELN (A - B)

      ELSE IF OPERATION = '*' THEN

         WRITELN ( A* B)

      ELSE IF OPERATION = '/' THEN

         WRITELN (A / B)

   UNTIL FALSE

END.

Pascal

Pascal es un lenguaje de programación de alto nivel de propósito general; esto es, se puede utilizar para escribir programas para fines científicos y comerciales.

El lenguaje de programación Pascal fue desarrollado por el profesor Niklaus (Nicolás) Wirth en Zurich, Zuiza, al final de los años 1960s y principios de los 70s. Wirth diseñó este lenguaje para que fuese un buen primer lenguaje de programación para personas comenzando a aprender a programar. Pascal tiene un número relativamente pequeño de conceptos para aprender y dominar. Su diseño facilita escribir programas usando un estilo que está generalmente aceptado como práctica estándar de programación buena. Otra de las metas del diseño de Wirth era la implementación fácil. Él diseñó un lenguaje para el cual fuese fácil escribir un compilador para un nuevo tipo de computadora.

program Sorting;

{

Este programa lee un natural y una secuencia de N caracteres de la entrada estandar; construye un indice para ordenarlos de menor a mayor e imprime en la salida la secuencia ordenada.

}

uses CRT;

Const Max = 10;

Espacio = ' ';

Enter = chr (13);

type Indice = 1..Max;

Cantidad= 0..Max;

SecOfChar = record

elems : array [Indice] of char;

ult : Cantidad;

end;

SecOfInd = record

elems : array [Indice] of Indice;

ult : Cantidad;

end;

Natural = 0..MaxInt;

function PosMin (idx: SecOfInd; i: Indice; s: SecOfChar): Cantidad;

{ Devuelve la posicion en el indice idx del menor caracter en s, para

las posiciones >= i. }

var j: Indice;

pm: Cantidad;

begin

if i > idx.ult then

pm := 0

else begin

pm := i;

for j := i+1 to idx.ult do

if s.elems[idx.elems[j]] < s.elems[idx.elems[pm]] then

pm := j;

end;

PosMin := pm;

end;

procedure Swap (var idx: SecOfInd; i,j: Indice);

{ Intercambia las posiciones i j en idx. }

var tmp: Indice;

begin

if (i<=idx.ult) and (j<=idx.ult) then begin

tmp := idx.elems[i];

idx.elems[i] := idx.elems[j];

idx.elems[j] := tmp;

end;

end;

procedure InicInds (var idx: SecOfInd; cant: Indice);

{ Construye la secuencia de indices 1,2,3,...,n. Sera el indice

inicial para el ordenamiento de una secuencia de caracteres

c1,c2,...,cn. }

var n: Natural;

begin

n := cant;

idx.ult := n;

while n > 0 do begin

idx.elems [n] := n;

n := n-1;

end;

end;

procedure InicSecChar (var s: SecOfChar);

{ Devuelve la secuencia vacia. }

begin

s.ult := 0;

end;

function Llena (s: SecOfChar): Boolean;

begin

Llena := s.ult = Max;

end;

{ PRE: not Llena(s) }

procedure InsCar (var s: SecOfChar; c: char);

{ Inserta el caracter c en la secuencia s }

begin

s.ult := s.ult + 1;

s.elems [s.ult] := c;

end;

procedure IndSelSort (s: SecOfChar; var ind: SecOfInd);

{ Construye el indice que ordena la secuencia s. Ordena el indice

inicial 1,2, ..., n por el metodo de selection sort }

var i: Indice;

begin

InicInds (ind, s.ult);

for i := 1 to ind.ult-1 do begin

Swap (ind, i, PosMin (ind, i, s));

end

end;

procedure WriteSorted (idx: SecOfInd; s: SecOfChar);

{ Imprime en la salida estandar la secuencia s ordenada segun el

indice idx }

var i: Indice;

begin

write ('Ordenado: ');

for i := 1 to idx.ult do

write (s.elems[idx.elems[i]],' ');

writeln;

end;

procedure LeerCar (var c: char; var ok: boolean; sep: Char);

{ Lee de la entrada estandar un caracter seguido del caracter sep }

var c1, c2: char;

begin

c := ReadKey; write (c);

c1 := ReadKey; write (c1);

ok := c1 = sep;

end;

procedure LeerSecOfChar (var s: SecOfChar; cant: Natural; var ok: Boolean);

{ Construye una secuencia de cant caracteres provistos por el

procedimeinto LeerCar. Si cant > Max trunca. }

var bien: Boolean;

i: Natural;

ch, sep: Char;

begin

writeln ('Ingrese ',cant, ' caracteres separados por blancos. Enter para terminar ');

write (' > ');

InicSecChar (s);

i := 1;

ok := true;

sep := Espacio;

while ok and (i <= cant) and not Llena (s) do begin

if i = cant then sep := Enter;

LeerCar (ch, bien, sep);

i := i+1;

ok := ok and bien;

if ok then

InsCar (s, ch);

end;

end;

procedure LeerCant (var n: Natural);

{ Lee de la entrada estandar un natural <= Max }

begin

repeat

writeln ('Ingrese cantidad de caracteres (<=',Max,')');

write (' > ');

readln (n);

until n <= Max;

end;

procedure Continuar (var seguir: Boolean);

var car: Char;

begin

writeln;

writeln ('Otro ? (s/n)');

write (' > ');

car := ReadKey;

writeln (car);

seguir := car in ['s','S'];

end;

var cant: Natural;

cars: SecOfChar;

inds: SecOfInd;

seguir, ok: boolean;

begin

repeat

ClrScr;

LeerCant (cant);

LeerSecOfChar (cars, cant, ok);

if ok then begin

IndSelSort (cars, inds);

writeln;

WriteSorted (inds, cars);

end

else begin

writeln;

writeln ('Error en los datos');

end;

Continuar (seguir);

until not seguir;

end.

 

 

PERL
Es un lenguaje especializado en el procesamiento de textos, particularmente extraer y validar las respuestas a cuestionarios incluidos en páginas web.
 

PL/1
EL "PL/1" es un lenguaje multi-propósito creado por IBM y SHARE, especialmente a raíz del paso de la segunda a la tercera generación de computadores, cuando se preveía la creciente difusión de estas máquinas y su posible uso en una gama creciente de actividades. Pretendía ampliar las posibilidades del FORTRAN fusionando conceptos provenientes del COBOL y el ALGOL.
La gran cantidad de instrucciones, tipos de datos y casos especiales que contempla lo hacen difícil de aprender y dominar, razón de su poca difusión.

EJEMPLO

TRAPZ: PROCEDURE OPTIONS (MAIN);

  DECLARE (J,K)    FIXED DECIMAL (2),

               AREA    FIXED DECIMAL (8,6);

  PUT SKIP EDIT ('AREA BAJO LA CURVA') (X(9),A);

  PUT SKIP;

  DO K=4 TO 10;

      AREA=0.5/K;

      DO J=1 TO K-1;

           AREA=AREA+((J/K)**2)/K);

       END;

  PUT SKIP EDIT      ('PARA DELTA X=1/',K,AREA)

                              (X(2),A,F(2),X(6),F(9,6);

   END;

END;


 

PHP
Lenguaje que se acopla al HTML (páginas web) para definir procedimientos que ha de realizar el servidor de web, por ejemplo procesar un formulario, enviar o extraer datos de una base de datos (acoplándose también con un lenguaje de tipo SQL), enviar una u otra página web según determinadas condiciones prefijadas por el programador, etc.
 
 

PROLOG
Los primeros años de la décado del 70 son conocidos como un período de "crisis del software", en que se descubrió que la creación de buenos programas involucraba costos mayores que los del hardware que los ejecuta. También se hacía patente una creciente necesidad de procesar "conocimientos" (algo mucho más amplio y complejo que los datos cuantitativos o meras "secuencias de caracteres" a los cuales se reducen muchos lenguajes de programación). Esta crisis llevó a investigar numerosas alternativas, entre las cuales nuevos lenguajes no basados en instrucciones algorítmicas o procedimientos. Si el hombre "procesa" más información por inferencia lógica que por cálculo, ¿no podría la máquina hacer lo mismo?
PROLOG ("PROgramación en LOGica") es una respuesta a esta crisis, producto del avance de la lógica moderna (de tipo funcional). Lo crearon A. Colmenauer y Ph. Roussel, con la colaboración de R. Kowalski, simultáneamente en la Universidad de Aix-Marseille (Francia) y Edimburgo (Gran Bretaña). Se basa en el cálculo de predicados de primer orden y en el principio de resolución de Robinson. En vez de ser algorítmico ("procedural" en inglés, término sin traducción), es decir concebido como un conjunto de instrucciones que la máquina debe ejecutar en forma secuencial, es "declarativo", es decir basado en definiciones (de "hechos" o "reglas", como se explica más abajo).

EJEMPLO

Si sabemos que una línea aérea une París con Río con el vuelo 36 y otra une Río con Santiago con el vuelo 71, concluimos sin dificultad alguna que es posible viajar de París a Santiago con una escala en Río.

En lógica funcional, los datos básicos ("hechos" en terminología PROLOG) podrían escribirse:

   une(Paris,Rio,Vuelo36).

   une(Rio,Santiago,Vuelo71).

Vemos que la relación ("une") es la misma y que hay un término común en la lista de argumentos (lo que hay entre paréntesis). Solo falta explicitar una regla idéntica a la que se usa para extraer una conclusión a partir de dos premisas en un silogismo:

   camino(Paris,Santiago) <- une(Paris, x, n),

                             une(x, Santiago, m).


o sea "Hay un camino entre París y Santiago si algún vuelo (n) une París con una ciudad 'x' y (&) otro vuelo (m) une esta ciudad 'x' con Santiago.

Un "programa" en PROLOG se conforma con estos dos tipos de expresiones (llamadas "cláusulas"): "hechos" y "reglas". Una cláusula con forma de hecho y seguida de un '?' constituye la forma habitual de consultar la información. Si no contiene ninguna variable, el programa verifica si existe una "copia" en la lista de hechos y contesta por sí o no. Si contiene una o más variables busca cuales se ajustan a la descripción o pueden ser deducidas mediante las reglas y señala el valor correcto de las diferentes variables (o bien "No" si no hay respuesta posible).
 
 

SQL
Lenguaje desarrollado especialmente para facilitar la consulta de bases de datos (BD), acotando progresivamente la búsqueda (de ahí el nombre de "Sequential Query Language").
Existen hoy numerosas aplicaciones de administración de bases de datos que recurren al SQL (Las más conocidas, potentes - y caras - son Oracle e Informix).
Hoy se pueden acoplar las bases de datos a hipertextos (páginas web), para lo cual las buenas aplicaciones ya traen módulos que hacen la conexión. El lenguaje PHP del cual hablamos más arriba también sirve para definir procedimientos de inserción y de consulta de datos en BD (Base de Datos) que funcionan con SQL.

Linux

Linux es una implementación del sistema operativo UNIX (uno más de entre los numerosos clónicos del histórico Unix), pero con la originalidad de ser gratuito y a la vez muy potente, que sale muy bien parado (no pocas veces victorioso) al compararlo con las versiones comerciales para sistemas de mayor envergadura y por tanto teóricamente superiores. Comenzó como proyecto personal del –entonces estudiante- Linus Torvalds, quien tomó como punto de partida otro viejo conocido, el Minix de Andy. S. Tanenbaum (profesor de sistemas operativos que creó su propio sistema operativo Unix en PCs XT para usarlo en su docencia). Actualmente Linus lo sigue desarrollando, pero a estas alturas el principal autor es la red Internet, desde donde una gigantesca familia de programadores y usuarios aportan diariamente su tiempo aumentando sus prestaciones y dando información y soporte técnico mútuo. La versión original -y aun predominante- comenzó para PCs compatibles (Intel 386 y superiores), existiendo también en desarrollo versiones para prácticamente todo tipo de plataformas:

PowerPC <http://www.cs.us.es/archive/linuxppc/>,

Sparc <http://www.geog.ubc.ca/sparclinux.html>,

Alpha <http://www.azstarnet.com/~axplinux>,

Mips <http://www.fnet.fr/linux-mips/>, etc.

De todas ellas la más reciente en este momento es la versión para PowerMac <http://www.mklinux.org> (el PowerPC de Apple) basada en el microkernel Mach 3.0 y de la que ya hay una distribución para desarrolladores avalada directamente por Apple y OSF pero conservando el espíritu (gratuito, de libre distribución, etc) de la version original. Un servidor la acaba de probar hace unos días y se ha llevado una grata sorpresa (aún tendrá muuuchos fallos, pero para ser una primerísima versión y el poco tiempo que lleva en marcha, ha avanzado más de lo que me esperaba).

Ejemplo de linux:

Compilar el Kernel

Dado que un diskette sólo almacena 1.44 Megabytes (1440 Kilobytes) de datos, no puedes el mismo kernel que utilizas al diskette. Primero debes conseguir los fuentes del núcleo y descomprimirlos en /usr/src/linux. Luego ejecuta la siguiente orden desde el directorio

/usr/src/linux:

make config

Configura solamente aquello que realmente necesites. Yo, personalmente, sólo configuro el soporte para "ext2", soporte para la disquetera (floppy disk), y soporte para "PPP". Tus elecciones pueden se diferentes en función de lo que decidas incluir. Ahora introduce el siguiente comando:

make dep; make clean; make zImage

¡make zImage es muy importante! Comprime el kernel definitivo. Después de que termine la compilación, deberás buscar el nuevo núcleo en /usr/src/linux/arch/i386/boot bajo el

nombre de zImage.

El sistema de ficheros: No es solamente un conjunto de ficheros

Ahora hemos de crear el sistema de ficheros (en inglés: filesystem, fs) para el diskette. En vez de copiar los ficheros tal cual directamente al diskette, los comprimiremos antes de copiarlos. Esto nos hará un poco más difícil la faena de modificar todo permanentemente. Primero tecleamos el siguiente

comando:

dd if=/dev/zero of=[DEVICE] bs=1k count=3000

Donde [DEVICE] es "lugar" en el disco duro donde vas a guardar el sistema de ficheros descomprimido. Luego, introduce el siguiente comando y pulsa ENTER, sustituyendo [DEVICE] por el directorio en tu disco duro donde estás guardando el sistema de ficheros descomprimido:

mke2fs -m 0 [DEVICE]

Si make2fs te pregunta si realmente quieres hacer esto (Do you really want to do this?), acepta tecleando "y" (yes).

Después tenemos que montar este sistema de ficheros que hemos creado. Para ello, el núcleo que utilices tiene que permitir "montar ficheros", en otras palabras, ha de tener habilitada la posibilidad de "loopback devices". Para ello has de compilar el núcleo de tu máquina (no el núcleo que hemos creado, sino el de tu propia máquina) con la opción:

Loopback device support (CONFIG_BLK_DEV_LOOP) [M/n/y/?]

bien como módulo (M) o en el mismo núcleo (Y). Si lo compilas como módulo (lo más recomendable) luego tienes que insertar el módulo modprobe loop !No olvides rearrancar la máquina si has tenido que recompilar el núcleo!

mount -t ext2 DEVICE /mnt

Si se queja la orden mount puedes intentar con la siguiente orden:

mount -o loop -t ext2 DEVICE /mnt

Ahora debes copiar todos los ficheros que necesites en el nuevo sistema de ficheros. Primero, ponte en el directorio /mnt, (cd /mnt), y crea los siguientes directorios:

/dev

/pro

/etc

/bin

/lib

/mnt

/usr

Ahora crearemos el directorio /dev tecleando lo siguiente:

cp -dpR /dev /mnt/dev

Si se te acaban los i-nodos del diskette, puedes ir a /mnt/dev y borrar los archivos de dispositivo que no necesites. Cuando acabes de copiar los ficheros necesarios para /dev, ves a /etc. Para estar seguro copia todos los ficheros de /etc a /mnt/etc:

cp -dpR /etc /mnt/etc

Luego copia todo del directorio /lib en /mnt:

cp -dpR /lib /mnt/lib

Para el directorio /bin, copia sólo aquello que creas que necesitas en /mnt/bin.

Copiar todo a tu diskette

Ahora hemos de copiar todo en el/los diskette/s. Para hacer esto, debemos comprimir ahora el sistema de ficheros tecleando las siguientes ordenes:

cd /

umount /mnt

dd if=[DEVICE] bs=1k | gzip -9 > rootfs.gz

Ahora es importante comprobar el tamaño del núcleo. Ponte en /usr/src/linux/arch/i386/boot y teclea "ls -l". Luego divide el tamaño del núcleo entre 1024.

Por ejemplo, si el tamaño es de 250000 bytes, entonces son 245 KB. En adelante, reemplaza [ROOTBEGIN] en las ordenes que aparezca por el número total de kilobytes que has calculado. Ahora copia el kernel al diskette usando el siguiente comando:

dd if=zImage of=/dev/fd0

Este comando grabará el kernel en el diskette. Luego introduce el siguiente comando para que el kernel pueda encontrar la raíz del sistema de ficheros en el diskette.

rdev /dev/fd0 /dev/fd0

Ahora tendrás que hacer un pequeño cálculo en hexadecimal. Suma 4000 al equivalente en hexadecimal de [ROOTBEGIN] (que en nuestro ejemplo es F5). Convierte el resultado a decimal y teclea el siguiente comando, sustituyendo 16629 con el resultado que tú has obtenido:

rdev -r /dev/fd0 16629

Finalmente, teclea lo siguiente para copiar el sistema de ficheros al diskette:

dd if=/rootfs.gz of=/dev/fd0 bs=1k seek=[ROOTBEGIN]

El sistema de ficheros raíz será copiado al diskette justo después del kernel. ¡Ya lo tienes! Para el segundo diskette, el proceso es más fácil. Copia los ficheros que quieras en el diskette. No obstante, para poder usar los ficheros que hay en el segundo disco, tendrás que entrar lo siguiente después de arrancar con el diskette:

mount /dev/fd0 /usr

 

 

COMPILADOR

El "COMPILADOR" es un programa especial destinado a traducir automáticamente un lenguaje de segunda o tercera generación en código de máquina (bits), de tal modo que todas las instrucciones y los datos contenidos en el programa estén en condiciones de ser reconocidos y ejecutados por la CPU. El programa original se llama "programa fuente" y se conserva igual que un texto preparado con un procesador de palabras. La "traducción" es una serie diferentes de caracteres (utilizables por la CPU) que debe ser grabado en otro espacio de memoria auxiliar. Se llama "programa objeto". El usuario "carga" el programa objeto en la memoria principal (RAM) cuando desea utilizarlo. (Los programas comerciales que compramos vienen bajo la forma de "programa objeto").
Dado que cada procesador tiene su propio "set" de instrucciones, los compiladores deben estar asociados a los diversos modelos de procesadores (p.ej. Intel 8088, Motorola 68000, PowerPC). Y ya que existen múltiples lenguajes de más alto nivel que el código de máquina, también están ligados a dichos lenguajes. En consecuencia, debería haber un número de compiladores igual al número de modelos de procesadores multiplicado por el número de lenguajes (ej. compilador de PASCAL para Motorola 68000, para Intel 8088, etc.; de BASIC para Motorola 68000, para Intel 8088, etc.; etc.).
En la realidad el número es menor, ya que no se confeccionan compiladores para todas las combinaciones posibles.
 
 

INTERPRETE

Los "INTERPRETES" son programas especiales destinados a "traducir" programas redactados en lenguajes de tercera generación, pero operan de un modo distinto de los compiladores. Aquí, no se crea un "programa objeto", sino que -cada vez que se desea usar el programa fuente- se opera leyéndolo y traduciéndolo instrucción por instrucción en lenguaje de máquina. En este caso, el intérprete debe estar previa y constantemente disponible en la memoria principal, ya que de él depende la ejecución del programa.
Los primeros microcomputadores (especialmente los modelos "hogareños") se entregaban con un intérprete de BASIC "incorporado", lo cual quiere decir que tenían un chip con el intérprete grabado en ROM, adjunto al procesador. De este modo podían traducir y ejecutar instrucciones de BASIC desde el momento en que se encendían.