Sunteți pe pagina 1din 18

Capı́tulo 2

Teorı́a de valores y tipos

Los valores o datos organizados proveen información, todos los sistemas de información tienen
como objetivo general el de hacer algo requerido por los usuarios con esta información. Por lo
tanto el estudio de los valores o datos es imprescindible dentro del área de las ciencias de la
computación.

En este capı́tulo se estudiarán los distintos tipos de valores en los lenguajes de programación y
se introducirá una notación formal, para no referirse a una sintaxis concreta de cada lenguaje
de programación. Finalmente se incorporarán conceptos de los lenguajes modernos en el manejo
de los valores.

2.1. Valor

Nuestro mundo gira en torno a valores que adquieren sentido cuando están organizados, por
ejemplo: ‘‘Marı́a’’, 20, 23452, ‘‘Rojas’’, 19, 545632, son valores distintos que al pare-
cer organizados cobrarı́an sentido. A continuación se definirá éste término dentro del contexto
de nuestro estudio.

Definición 1 Un valor es cualquier entidad que puede ser evaluada, almacenada en una estruc-
tura de datos, pasada como un argumento a una función o procedimiento, retornado como un
resultado de una función, etc. Cualquier entidad que existe durante una computación [18] .

Todos los lenguajes de programación involucran el uso de valores de alguna manera. Por ejemplo
en Java:

Valores primitivos (enteros, booleanos, etc).

Valores por referencia (objetos, cadenas, etc.).

1
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 2

en Haskell:

Valores primitivos (valores de verdad, enteros, reales, etc.).

Valores compuestos (tuplas, construcciones, cadenas, listas y abstracciones de funciones).

2.2. Tipo

Es útil agrupar los valores en tipos. Por ejemplo; los valores de verdad se distinguen claramente
de los valores enteros, puesto que existen operaciones propias para los valores de verdad que no
son aplicables a los valores enteros y también viceversa.

Definición 2 Un tipo es un conjunto de valores que tienen caracterı́sticas en común y exiben


un comportamiento uniforme bajo ciertas operaciones.

Es importante recalcar que todo el conjunto de valores en un tipo exhibe un comportamiento


uniforme bajo las operaciones asociadas con el tipo. Ası́ el conjunto {13,’e’, true } no es
un tipo; pero { false, true } es un tipo porque sus valores exhiben un comportamiento
uniforme bajo las operaciones de negación, conjunción y disyunción.

Cardinalidad

Algunas veces es necesario determinar cuantos elementos tiene un conjunto, es decir, cuantos
valores tiene un tipo. Se escribe “#S 00 para determinar el número de valores distintos en S. Por
ejemplo:

# Valor Verdad = 2

# Enteros = 2*maxEnt+1

2.3. Clasificación de los tipos

Todo lenguaje de programación tiene tipos primitivos cuyos valores son atómicos y tipos com-
puestos cuyos valores están compuestos a partir de otros valores más simples.

2.3.1. Tipos primitivos

Un tipo primitivo es aquel cuyos valores son atómicos y por lo tanto no pueden ser descompuestos
en valores más simples.
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 3

Lenguaje Sintaxis Conjunto de Valores Notación


Java, C++ bool { false, true } Valor Verdad
Pascal Boolean { false, true } Valor Verdad
Haskell, C++ int { ... -2, -1, 0, 1, 2 ...} Entero
Pascal Integer { ... -2, -1, 0, 1, 2 ...} Entero
Java, C++ Float { ...,-1.0,.. 0.0, .. ,..1.0, ...} Real

Cuadro 2.1: Ejemplos de tipos primitivos en distintos lenguajes.

Las opciones de tipos primitivos en un lenguaje de programación nos dicen mucho acerca del
área de aplicación predeterminada por el lenguaje. Un lenguaje predeterminado para el área de
comercio (por ejemplo Cobol) provee de tipos primitivos cuyos valores son cadenas de longitud
fija y los números de punto fijo. Un lenguaje predeterminado para la computación numérica (por
ejemplo Fortran) es probable que tenga tipos primitivos cuyos valores sean números reales (con
opción de precisión) y tal vez números complejos.

Tipos primitivos similares frecuentemente ofrecen lo mismo pero con distintos nombres en los
distintos lenguajes de programación. Por lo tanto, se utilizará una notación común (lenguaje
natural en español) para referirse a estos tipos, ver el cuadro 2.1.

En algunos lenguajes el programador puede definir completamente un tipo primitivo nombrando


sus valores. Tal tipo es llamado tipo enumerado, sus valores que se denominan y se listan de
manera explı́cita.

Ejemplo 1 Considerar la definición de tipos enumerados en C:

enum Mes {ene, feb, mar, abr, may, jun ,jul, ago, sep,
oct, nov, dic}

Un tipo primitivo discreto es un tipo cuyos valores tienen relaciones uno-a-uno con un rango de
enteros. Esto es un concepto importante en Pascal y Ada, en los cuales los valores de cualquier
tipo primitivo discreto pueden ser usados en una variedad de operaciones, tales como conteo,
selección de casos e indexado de arreglos.

2.4. Tipos compuestos

Un tipo compuesto (o tipo estructurado de datos) es un tipo cuyos valores son compuestos o
estructurados a partir de otros valores simples. Los lenguajes de programación soportan una
variedad amplia de estructuras de datos, por ejemplo: tuplas, registros, variantes, uniones, ar-
reglos, conjuntos, cadenas, listas, árboles, archivos seriales, archivos directos, relaciones, etc.
La variedad puede parecer muy amplia, pero estos tipos pueden entenderse en términos de un
pequeño número de conceptos estructurales. Estos conceptos se ven resumido en el cuadro 2.2.
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 4

Concepto Estructural Tipos Compuestos


Productos cartesianos Tuplas y registros.
Uniones disyuntas Variantes y uniones.
Mapeos Arreglos y funciones.
Conjuntos Potencia Sets.
Tipos recursivos Estructuras de datos dinámicas.

Cuadro 2.2: Conceptos estructurales para tipos compuestos.

Cada lenguaje de programación provee su propia notación para describir tipos compuestos. Para
definir los conjunto de valores para todos los tipos compuestos mencionados se introducirá una
notación matemática simple, estándar y satisfactoria. La notación es lo suficientemente poderosa
como para describir una variedad de estructuras de datos.

2.4.1. Producto cartesiano

La forma más simple de composición de valores es el producto cartesiano, donde se juntan


dos valores de posiblemente diferentes tipos. Se utilizará la notación S × T para representar el
conjunto de todos los pares ordenados de valores, tales que el primer valor de cada par es elegido
del primer conjunto S y el segundo valor del segunto conjunto T . Formalmente:

S × T = {(x, y)|x ∈ S; y ∈ T } (2.1)

Las operaciones básicas sobre un par ordenado de valores son simplemente la selección de su
primer componente y la selección de su segundo componente.

Podemos fácilmente inferir la cardinalidad del producto cartesiano:

#(S × T ) = #S ∗ #T

En general, se puede representar a las tuplas de la forma:

S1 × S2 × · · · × SN (2.2)

Las estructuras de datos pueden ser entendidas en términos de productos cartesianos, por ejem-
plo:

Ejemplo 2 Estructura de datos escrita en código C++.

struct empleado {
int codigo;
char *nombre;
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 5

float salario;
}

la misma estructura escrita en código de Pascal:

type empleado= record


codigo : Integer;
nombre : String;
salario: Real;
end

El código es distinto en ambos lenguajes, en términos formales la representación será la misma,


el registro empleado tiene 3 valores que conforman cada tupla en el conjunto Entero×Cadena×
Real. Es decir, el conjunto de valores de empleado en extenso es, por ejemplo:

empleado = {· · · , (100, “P erezJuan”, 3000), (101, “M oralesM aria”, 1500), · · · }.

Tupla homogénea

Una tupla homogénea es un caso especial del producto cartesiano, donde todos los componentes
de la tupla son elegidos del mismo conjunto. Se escribe de la siguiente manera:

Sn = S × · · · × S (2.3)

La cardinalidad de la tupla homogénea esta dada por:

#(S n ) = #(S)n

Tupla cero

Una tupla cero es un caso especial del producto cartesiano de la ecuación 2.3, donde S 0 contiene
exactamante una tupla sin valores. Se define:

U nit = {()} (2.4)

U nit corresponde al tipo void de C, o unit en ML.


Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 6

2.4.2. Unión disyunta

En una unión disyunta de dos conjuntos o tipos, cada valor es marcado con una etiqueta que
indica a que tipo pertene. Formalmente:

S + T = {izq x|x ∈ S} ∪ {der y|y ∈ T } (2.5)

Los valores elegidos de S están etiquetados con izq y los valores elegidos de T estan etiquetados
con der.

La cardinalidad de la unión disyunta es: #(S + T ) = #S + #T .

Se puede extender la unión disyunta para n tipos, entonces:

S1 + · · · + Sn

donde cada valor elegido de Si tiene una etiqueta i (elegida libremente).

Los registros invariantes de Pascal y Ada, las uniones de C++, los constructores de Haskell, etc.
pueden entenderse en términos de uniones disyuntas.

Ejemplo 3 Considere el registro invariante en Ada:

type Disco is (EsEnt, EsReal);


type EntOReal (which: Disco) is
record
case which is
when EsEnt => i: integer;
when EsReal => r: float;
end case;
end record;
. . .
x : EntOReal:=(EsReal,2.3); {es una declaracion con asignacion}

o en ML:

datatype EntOReal = EsEnt of int | EsReal of real;

Las etiquetas EsEnt y EsReal se utilizan para identificar el tipo de valor de EntOReal, en
conceptos estructurales se representará el tipo de EntOReal como: Entero + Real
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 7

2.4.3. Mapeo

El concepto de mapeo o función es muy importante en lenguajes de programación, y aparece


en muchas formas. Considerar m que mapea cada valor x del cojunto S hacia el conjunto T .
Entonces el valor obtenido recibe el nombre de imagen de x bajo m, y convencionalemente se
escribe:
m : S −→ T

para determinar que m es un mapeo de S a T .

La notación S −→ T determina el conjunto de todos los mapeos. Formalmente:

S −→ T = {m|x ∈ S =⇒ m(x) ∈ T } (2.6)

La cardinalidad de S −→ T = #T #S .

Ejemplo 4 Dado el parámetro n de tipo entero, la función par retorna como resultado true si
n es par, false en caso contrario.

bool par(int n) {
return (n mod 2==0);
}

Esta abstracción de función implementa un mapeo particular del conjunto de los enteros a los
valores de verdad, en términos formales:

Entero −→ V alor V erdad = {· · · , 0 → true, 1 → f alse, 2 → true, · · · }.

2.4.4. Conjuntos potencia

Considerar los valores de S, estamos interezados en los subconjunto de S que son por sı́ mismos
valores de S. El conjunto de todos estos subconjuntos es llamado conjunto potencia de S, y es
escrito ℘(S). Formalmente:

℘(S) = {s|s ⊆ S} (2.7)

Las operaciones básicas sobre un conjunto usualmente son las operaciones de la teorı́a de con-
juntos: prueba de membresı́a, prueba de inclusión, unión, e intersección.

Cada valor en S puede ser miembro o no miembro de un conjunto en particular de S. Por lo


tanto la cardinalidad del conjunto potencia de S esta dado por:
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 8

#(S) = 2#S

Pascal es uno de los pocos lenguajes de programación que soporta conjuntos en forma directa.
Un tipo conjunto en Pascal tiene la sintaxis de la forma: set of T.

Ejemplo 5 Considerar el conjunto en Pascal:

Type Color = (rojo, verde, azul);


Tinte = set of Color;

El conjunto de valores de Tinte es Color, es decir, el conjunto de todos los subconjuntos de


Color = (ojo, verde, azul). Estos valores son los siguientes ocho conjuntos: {} {rojo} {azul}
{verde} {rojo, azul} {azul, verde} {verde, rojo} {rojo, verde,azul}.

Pascal permite solamente conjuntos de valores de tipos primitivos discretos (es decir, conjunto
de valores de verdad, caracteres, enteros, enumerandos y conjuntos de enteros), debido a estas
restricciones se permite una implementación muy eficiente de conjuntos.

2.4.5. Tipos recursivos

Un tipo recursivo es aquel cuyos valores estan compuestos a partir de otros valores del mismo
tipo. Un tipo recursivo es definido en términos de sı́ mismo. En general, el conjunto de valores
de un tipo recursivo T , será definido por un conjunto de ecuaciones de la forma:

T = ···T ··· (2.8)

en cuanto a la cardinalidad, en un tipo recursivo es indeterminada, ver por ejemplo el caso de


las listas en la siguiente sección.

Listas

Una lista es una secuencia de valores. Una lista puede tener cualquier número de componentes,
incluyendo nada. El número de componentes es llamado longitud de la lista. Una lista sin
componentes es llamada lista vacı́a. Una lista es homogénea si todos los componentes son del
mismo tipo.

Podemos definir como una lista vacı́a o como un par ordenado que consiste de un entero y el
resto de la lista (su cola). Esta es una definición recursiva y es escrita de la siguiente manera:

Lista Enteros = U nit + (Enteros × Lista Enteros)


Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 9

Generalizando :
L = U nit + (S × L)

L es una lista de valores elegidos del conjunto S.

Vamos ha introducir una nueva notación debido a su utilidad, para toda la lista infinita de
valores elegidos de S, ası́:

S ? = U nit + (S × S ? )

Tratemos de determinar la cardinalidad de S ? :

#S ? = #U nit + #(S × S ? )
#S ? = 1 + (#S ∗ #S ? )
#S ? = 1 + (#S ∗ (1 + (#S ∗ #S ? ))
#S ? = 1 + (#S ∗ (1 + (#S ∗ #(· · · ))

Como se pudo ver la cardinalidad de un tipo recursivo es indeterminada.

Los lenguajes funcionales permiten definir tipos recursivos directamente, ver el ejemplo 7, escrito
en ML donde se define una lista de enteros.

Ejemplo 6 Definición recursiva de lista en ML:

datatype intlist = nil


| cons of int*intlist

En cambio en otros lenguajes ésto no es posible de manera directa, en C++ por ejemplo, se
definen los tipos recursivos de manera indirecta a través de punteros.

Considerar el siguiente ejemplo para definir un árbol.

Ejemplo 7 Definición recursiva árbol en Haskell:

data Arbol a = Hoja a | Rama (Arbol a) (Arbol a)

En términos formales el tipo de Arbol es: α = α + (α × α). La letra griega α para indicar que
el tipo de árbol puede ser una familia de tipos (enteros, reales, caracteres, etc.), es decir de tipo
polimórfico.
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 10

2.5. Cadenas

Una cadena es una secuencia de caracteres. Las cadenas son soportadas por todos los lenguajes
de programación, sin embargo, no hay un consenso sobre cual serı́a la clasificación de éstas. Los
puntos de discusión son los siguientes:

1. ¿ Deberı́an las cadenas ser valores primitivos o compuestos?.


2. ¿ Que operaciones deberı́an proveerse?. Tı́picamente las operaciones de cadena son prueba
de igualdad, concatenación, selección de caracteres o subcadenas y el ordenamiento lexi-
cográfico. La forma cómo se llevarán a cabo éstas operaciones dependerán si las cadenas
con consideradas como: arreglos, listas o incluso clases.

Una posibilidad es hacer que la cadena sea un valor primitivo como en ML o Snobol, con valores
que son cadenas de cualquier longitud.

Otra propuesta es definir a las cadenas como arreglos de caracteres, entonces todas las op-
eraciones sobre los arreglos están automáticamente permitidas para las cadenas, con todas las
consecuencias que esto conlleva, por ejemplo en Pascal.

En Java las cadenas son clases, donde las operaciones permisibles sobre las cadenas son métodos.

En otros lenguajes las cadenas son secuencias de caracteres (listas) como en Prolog y Haskell.

2.6. Verificación de tipos

El conocimiento de la clasificación de los valores en tipos permite al programador utilizar a los


datos efectivamente. Una disciplina en la asignación de los tipos evita la ejecución de operaciones
sin sentido en los programas, por ejemplo: multiplicar un valor de verdad con un carácter.

Para asegurarse que las operaciones no deseadas sean prevenidas, la implementación del lenguaje
debe hacer la verificación de tipos sobre los operandos. Por ejemplo, antes que una multiplicación
sea realizada, ambos operandos deben ser verificados para asegurarse que son números.

En el caso de tipos compuestos, se deben considerar tanto la forma de la composición y los tipos
de los componentes individuales.

En la implementación de los lenguajes, existe un grado importante de libertad en la verificación


de tipos, esta verificación puede ser realizada en tiempo de compilación o en tiempo de ejecución.

2.6.1. Lenguajes de tipificación estática

En un lenguaje de tipificación estática, cada variable y parámetro tiene un tipo fijo que es elegido
por el programador, ası́ el tipo de cada expresión y cada operación puede ser deducida con la
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 11

verificación de tipos en tiempo de compilación.

2.6.2. Lenguajes de tipificación dinámica

En un lenguaje de tipificación dinámica, sólo los valores tienen tipos fijos. Una variable o
parámetro no tiene un tipo designado, pero puede tomar valores de diferentes tipos en tiempo
de ejecución. Esto implica que la verificación de tipos de los operandos debe hacerse inmediata-
mente antes de realizar una operación en tiempo de corrida. Lisp y Smalltalk son ejemplos de
lenguajes dinámicamente tipados.

2.6.3. Tipificación estática frente a Tipificación dinámica

Debido a la verificación implı́cita en tiempo de corrida, la tipificación dinámica conlleva una


ejecución más lenta de los programas. Además, para hacer posible la verificación de tipos es
necesario que cada valor deba ser etiquetado con su tipo, lo que supone el uso de espacio de
memoria adicional.

El tiempo y el espacio adicional es evitado en los lenguajes de verificación de tipos estática,


por que toda la verificación de tipos se la hace en tiempo de compilación. Una ventaja muy
importante del tipificado estático es la seguridad que garantiza el compilador al detectar los
errores de tipos. Esto es importante por que muchos de los errores de tipos en la programación
son una proporción importante de errores en la programación.

La ventaja de la verificación de tipos dinámica es la flexibilidad, es decir, la re-utilización de


código, caracterı́stica muy importante en estos dı́as.

2.7. El principio de completitud de tipos

Considerar la siguiente lista de valores en Pascal:

valores primitivos,

valores compuestos,

punteros,

referencia a variables,

abstracciones de procedimientos y funciones.

La lista incluye abstracciones de procedimientos y funciones. Ellas cuentan como valores por que
pueden ser utilizadas como argumentos; pero no pueden ser evaluadas, ni asignadas, ni pueden
ser componentes de otros valores más complejos, son en efecto valores de segunda clase. Por otro
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 12

lado, los valores primitivos, arreglos, etc., pueden ser utilizados en todas las formas de definición
de valor, éstos son valores de primera clase.

Este tipo de distinción de clases era común en varios de los lenguajes de programación antigüos,
ahora en lenguajes más modernos, se evita este tipo de distinción y permite a todos los valores,
incluyendo a las abstracciones, ser manipuladas en forma similar a los valores primitivos, tal es
el caso de Haskell, donde todos sus valores son de primera clase.

Se puede caracterizar la consistencia de tipos siguiendo el siguiente principio:

Teorema 1 (El principio de completitud de tipos) Ninguna operación deberı́a ser arbi-
trariamente restringida en los tipos de los valores involucrados [18].

Éste principio señala que los lenguajes de programación no deberı́an discriminar operaciones
entre sus tipos, porque las restricciones arbitrarias tienden a reducir el poder expresivo de un
lenguaje de programación.

2.8. Sistemas de tipos

Los lenguajes de programación clásicos como Pascal y C tienen sistema de tipos muy simples.
Cada constante, variable, resultado de función, y parámetro formal debe ser declarado con un
tipo especı́fico. Un tipo de sistema como este es llamado monomórfico donde la verificación de
tipos es estática.

Desafortunadamente, la experiencia nos muestra que un sistema de tipos monomórfico no es


satisfactorio, especialmente para escribir código re-usable. Muchos algoritmos son naturalmente
genéricos, como por ejemplo un algoritmo de ordenamiento de un grupo de elementos.

2.8.1. Monomorfismo

Un sistema de tipos donde los valores tienen tipos definidos y únicos es llamado Sistema de tipos
Monomórfico.

Por ejemplo, en C/C++ cada función es forzada a devolver un tipo especı́fico y único de datos
(al menos que sea definida con un Template1 racias a los templates o plantillas, se permite el
polimorfismo de funciones en C++) como consecuencia, cada función es monomórfica.

No obstante, ningún lenguaje de programación tiene su sistema de tipos estrictamente monomórfi-


co, incluso en el Pascal antigüo, por ejemplo:

W rite(E)
1
G
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 13

Write, es una abstracción de procedimiento propia del lenguaje Pascal, el efecto de tal proced-
imiento depende del tipo de E, write simultáneamente denota muchos procedimientos distintos
cada uno con parámetro de distinto tipo, éste es un ejemplo de sobrecarga.

Otro ejemplo:
eof (F )
es una función propia del Pascal, ésta función verifica si es fin de archivo, su argumento F es un
archivo que puede ser de cualquier tipo, éste tipo de función es llamada polimórfica.

En conclusión, el sistema de tipos de Pascal es monomórfico para el programador, sin embargo


presenta ciertas abstracciones propias del lenguaje que no obedecen a este sistema de tipos.

2.8.2. Sobrecarga (Polimorfismo ad hoc)

Significa que un número de abstracciones distintas tienen el mismo identificador; estas abstrac-
ciones no necesariamente tienen tipos relacionados.

Considerar los códigos del ejemplo 8.

Ejemplo 8 La abstracción de función devuelve la suma dos enteros:

int suma(int n, int m)


{ return n+m; }

La abstracción de función devuelve la suma de dos reales:

float minimo(float n, float m)


{ return n+m; }

La abstracción de función devuelve la suma de tres enteros:

int minimo(int n, int m, int l)


{ return n+m+l; }

Consideremos la llamada suma(1,5);, por el número de parámetros y la correspondencia de tipos


se puede notar que la función invocada será la primera, este tipo de sobrecarga se denomina
sobrecarga independiente del contexto. Note que el operador + también es sobrecargado.

Se debe advertir que el lenguaje deberı́a establecer reglas para evitar la ambigüedad al invo-
car funciones sobrecargadas. Por ejemplo con la llamada suma(2.5,3) ¿cuál de las funciones
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 14

será invocada?. Cada lenguaje tiene una forma distinta de encarar éste problema, en Java por
ejemplo se hacen conversiones de tipos internamente sin perder información.

Para identificar la función ha ser invocada, aparte de utilizar el número de parámetros o los
tipos de los parámetros, además se puede utilizar información del contexto de la llamada, lo que
se denomina sobrecarga dependiente del contexto.

Ejemplo 9 Considere el ejemplo en Ada [6]:

procedure overload is

function max(integer x, integer y) -- funcion 1


return integer is
begin
if x>y then return x;
else return y;
end if;
end max;

function max(integer x, integer y) -- funcion 2


return float is
begin
if x>y then return float(x);
else return float(y);
end if;
end max;

a: integer;
b: float;
begin
a:=max(2,3); -- invocacion a funcion 1
b:=max(2,3); -- invocacion a funcion 2
end overload.

2.8.3. Polimorfismo

Es una propiedad donde una única abstracción actúa sobre una familia de tipos relacionados; la
abstracción opera uniformemente sobre sus argumentos, cualquiera sean sus tipos. Utilizaremos
letras griegas para referirnos a familias de tipos. Existen distintas formas de polimorfismo, incluso
la sobrecarga se dice que es una clase de polimorfismo. Sin embargo, el propósito verdadero del
polimorfismo son las funciones polimórficas, como en el siguiente ejemplo:

Ejemplo 10 Considere el ejemplo en Haskell:


Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 15

max x y = x > y

Considere el ejemplo en C++, con el uso de Templates:

template <typename T>


T max ( T x, T y)
{return x>y? x: y ;}

Examine el tipo variable (variant) de Object Pascal, que es capaz de albergar valores que cambien
su tipo en tiempo de ejecución, lo cual es útil cuando no se conoce el tipo de los datos en tiempo
de compilación [7].

Ejemplo 11 En Object Pascal:

Program UnEjemploConVariant
var Comodin1, Comodin2, Comodin3, Comodin4 : Variant;
begin
Comodin1:=1.37;
Comodin2:=’Esto es una cadena’;
Comodin3:=’345.98’;
Comodin4:=Comodin1+Comodin3;
end.

El polimorfismo, es un concepto importante que merece ser estudiado con mayor detenimiento.

2.8.4. Conversión de tipos

Debido a la necesidad de convertir valores de un tipo a valores de otro tipo, algunos lenguajes
asocian la conversión en su sistema de tipos de forma que las conversiones se las haga en forma
automática, en algunos casos el programador debe hacer explı́citas estas conversiones.

Coerción

Es la conversión implı́cita o automática de un tipo a otro. Por ejemplo: Sea la sqrt una función
que calcula la raı́z cuadrada de un número real. La llamada sqrt(5) presenta como argumento
el número entero 5, este valor es automáticamente convertido al valor real 5.0, sin que el
programador se percate de ello para que pueda efectuarse la operación.

Ejemplo 12 Considere el System.out.println de Java.


Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 16

class Imprime{
public static void main(Strings args[]) {
int i=2; double x=8.1; String p="palabra";
System.out.println(i+x);
System.out.println(p+i*x);
}
}

Conversión explı́cita

En la conversión explı́cita el programador se encarga de hacer las conversiones directamente en


código (conocida como casting). La forma de escritura de ésta conversion dependerá del lenguaje,
ver el siguiente ejemplo en código C y C++.

Ejemplo 13 En C:

...
int x;
...
x = (int) (1.5 + (double) (x/2));
...

En C++:

...
int x;
...
x = int(1.5 + double(x/2));
...
Bibliografı́a

[1] EDDY BLAIDER ABURTO CORREA. Programación en Java 2. Editorial MegaByte,


(2001).

[2] DACONTA MICHAEL C. Java for C/C++ programmers. Wiley & Sons. (1996).

[3] DEITEL H. M. - DEITEL P.J. Como programar en C/C++. Prentice Hall. (1994).

[4] FLANAGAN DAVID. Java Examples, in a Nutshell. A tutorial Companion to Java in a


Nutshell. O’ Really (1997)

[5] JOYANES AGUILAR LUIS. Programación orientada a objetos. Mc Graw Hill. (1998).

[6] LOUDEN KENNETH C. Lenguajes de programación, principios y práctica. Segunda Edi-


ción. Thomson (2004).

[7] MORAL VICTOR. Delphi 4 . Prentice Hall. (1999).

[8] NAUGHTON PATRICK - SHILDT HERBER. Java2. (1999)

[9] PEYTON JONES SIMON L. The implementation of Functional Programming Languages,


Prentice Hall, (1987).

[10] PITTMAN TOM.Tools for the professional programmer, The return of tiny basic. Dr.
Dobb’s. (January 2006)

[11] READE CHIRS. Elements of Functional Programming. Addison Wesley. (1989).

[12] SAMMMET JEAN E. Programming Language: History and Future. Communications of the
ACM, Volume 15, Number 7, July 1972.

[13] SCOTT MICHAEL L. Programming Language pragmatics. Morgan Kauffman (2000).

[14] SEBESTA ROBERT W. Concepts of Programming Language. The Benjamin/Cummings


Publishing Company, Inc. (1989).

[15] SWAINE MICHAEL. The World of Software Development: Ruby On Rails. Dr. Dobb’s.
(June 2006).

[16] SWAINE MICHAEL. Software Tools for the professional programmer: Programmings
Paradigms. Dr. Dobb’s. (July 2005).

17
Estructura y Semántica de Lenguajes de Programación - Cap2. Teorı́a de valores y tipos - MSc. Patricia E. Romero Rodrı́guez 18

[17] PERELMAN-HALL DAVID. Tools for the professional programmer, Sorting in Java & C#.
Dr. Dobb’s. (January 2006)

[18] WATT DAVID A. Programming Language Concepts and Paradigms. Prentice Hall (1990).

[19] WATT DAVID A. Programming Language Syntax and Semantics. Prentice Hall (1991).

S-ar putea să vă placă și