6. PARAMETRIZACIÓN 1

Download Report

Transcript 6. PARAMETRIZACIÓN 1

6. PARAMETRIZACIÓN
1
Parametrización




Los parámetros pertenecen a los subprogramas
Permiten independizar la funcionalidad abstracta de
las instancias de uso con datos concretos
Cada instancia de uso asocia parámetros actuales
con parámetros formales
Los elementos comprometidos en la representación de
una variable se utilizan para definir diferentes modelos
de parametrización
2
Parametrización
Nombre


Tipo
Referencia
Valor
Parametrización de datos
 Nombre
 Referencia
 Valor
Parametrización de tipos
 Tipo
3
Parametrización



Sin embargo, en la RAM de un computador sólo se
representan
 Datos
 Códigos
Y, como también es posible parametrizar códigos, se
debe definir un último modelo
Parametrización de subprogramas
4
Parametrización de datos
5
Opciones de llamada




Por Nombre
Por Referencia
Por Copia
 Por Valor
 Por Resultado
 Por Valor-Resultado
Por Indirección
6
Subprogramas de ejemplo
void uno(<Modalidad> int a, <Modalidad> int b)
{
a = 7;
b = 5;
}
void cero()
{ int c, d;
c = 5;
d = 7;
Uno(c, d);
cout << c << d;
}
7
Llamada Por Nombre




<Modalidad> ::= name
Sólo la provee lenguaje Algol
Cuando se invoca un subprograma se aplica la
denominada regla de sustitución
La regla de sustitución establece el reemplazo del
nombre del parámetro formal por el nombre del
respectivo parámetro actual
8
Llamada Por Nombre
void cero()
{ int c, d;
c = 5;
d = 7;
uno(c, d);
cout << c << d;
}
void uno(name int a, name int b)
{
a = 7;
b = 5;
}
uno:
c
5
cero:
a
7
b
d
5 7
7 5
sustitución
d
a
c
b
Regla de
sustitución en uno
c = 7;
d = 5;
7y5
sustitución
9
Llamada Por Nombre
procedure uno;
var x : integer;
procedure dos(name y : integer);
var x : integer;
begin
x := 2;
write(y);
end;
begin
x := 1;
dos(x);
end;
Llamada: dos(x);
Regla de sustitución
x := 2;
write(x);
dos:
uno:
y
x
x
1
2
1
1
x
x
y
2
10
Llamada Por Nombre
procedure swap(name a, b : integer);
var temp : integer;
begin
temp := a;
a := b;
b := temp;
end;
Si antes de la llamada: i = 3 y
v[3] = 5
i=3
i=5
Llamada: swap(i, vi);
Regla de sustitución
temp := i;
i := v[i];
v[i] := temp;
Pero queda:
i=5 y
v[5] = 3
?
Efecto indeseado
i=5
1 2 3 4 5 6 7
1 2 3 4 5 6 7
1 2 3 4 5 6 7
4 6 5 2 7 1 3
4 6 3 2 7 1 3
4 6 5 2 3 1 3
11
Llamada Por Referencia




<Modalidad> ::= ref
La proveen lenguajes como Fortran, Pascal y C++
Cuando se invoca un subprograma, el parámetro
formal se convierte en alias del respectivo
parámetro actual, es decir,
La referencia del parámetro actual se copia como
referencia del correspondiente parámetro formal
12
Llamada Por Referencia
void cero()
{ int c, d;
c = 5;
d = 7;
uno(c, d);
cout << c << d;
}
void uno(ref int a, ref int b)
{
a = 7;
b = 5;
}
uno:
cero:
c
5
a
d
7
b
a
c
b
d
5 7
7 5
7y5
13
Llamada Por Valor




<Modalidad> ::= in
La proveen lenguajes como Pascal, C y Ada
Cuando se invoca un subprograma, se ejecuta la
asignación
 parámetro formal  parámetro actual
es decir,
El valor del parámetro actual se copia como valor
del correspondiente parámetro formal
14
Llamada Por Valor
void cero()
{ int c, d;
c = 5;
d = 7;
uno(c, d);
cout << c << d;
}
void uno(in int a, in int b)
{
a = 7;
b = 5;
}
uno:
cero:
c
5
a
57
d
7
b
75
Asignaciones en la llamada
a = c;
b = d;
c
d
a
b
5 7 5 7
7 5
5y7
15
Llamada Por Resultado




<Modalidad> ::= out
La provee lenguaje Ada
Cuando se invoca un subprograma, no existe copia de
un valor; pero, cuando el subprograma termina, se
ejecuta la asignación
 parámetro actual  parámetro formal
es decir,
El valor del parámetro formal se copia como valor
del correspondiente parámetro actual
16
Llamada Por Resultado
void cero()
{ int c, d;
c = 5;
d = 7;
uno(c, d);
cout << c << d;
}
void uno(out int a, out int b)
{
a = 7;
b = 5;
}
cero:
c
7
5
a
7
d
5
7
b
5
Asignaciones al finalizar
a
b
5 7 7
7 5
5
uno:
c = a;
d = b;
c
d
7y5
17
Llamada Por Valor-Resultado



<Modalidad> ::= in-out
La provee lenguaje Ada
Efecto combinado de
 Llamada Por Valor, al invocar un subprograma, y
 Llamada Por Resultado, el terminar la ejecución
de un subprograma
18
Llamada Por Valor-Resultado
void cero()
{ int c, d;
c = 5;
d = 7;
uno(c, d);
cout << c << d;
}
void uno(in-out int a, in-out int b)
{
a = 7;
b = 5;
}
c
7
5
a
5
d
5
7
b
7
Al llamar:
a = c;
b = d;
b
7 cero:
c
a
5
5 7 5
7 5 7
7
5
uno:
Al terminar:
c = a;
d = b;
d
7y5
19
Llamada Por Indirección





<Modalidad> ::= in
La provee lenguaje C
Se trata de una Llamada Por Valor en la cual, la
referencia del parámetro actual se copia como valor
del correspondiente parámetro formal
En la definición, se debe anteponer el operador de
indirección al parámetro formal
En la invocación, se debe anteponer el operador de
dirección al respectivo parámetro actual
20
Llamada Por Indirección
void cero()
{ int c, d;
c = 5;
d = 7;
uno(&c, &d);
cout << c << d;
}
c
100
d
300
Al llamar:
5 7
7 5
void uno(in int *a, in int *b)
{
*a = 7;
*b = 5;
}
uno:
a
b
a  referencia de c
b  referencia de d
cero:
100
300
c
d
5 7
7
a
b
100 300
5
7y5
21
Parametrización de tipos
22
Problema

La función

suma los n=40 elementos enteros de un arreglo v
Sin embargo, para sumar los n=60 elementos reales
de un arreglo a, se debe implementar otra función,
sintácticamente distinta pero semánticamente igual
int Suma(Vector v, int n)
{ int i, s=0;
for (i=0; i<n; i++)
s = s + v[i];
return s;
}
23
Solución
Parametrizar el tipo de dato
 Esta solución involucra un alto nivel de abstracción
que reduce el tamaño del código fuente
 La producción de subprogramas, que difieran sólo en
el tipo de dato de sus parámetros, se realiza en
tiempo de traducción
 Ejemplos de formas de parametrización de tipos:
 Unidades genéricas (lenguaje Ada)
 Plantillas de funciones (lenguaje C++)

24
Unidades Genéricas


Definición
 Una Unidad Genérica es una unidad formal
(modelo) cuyos parámetros se instalan en tiempo
de traducción para producir una unidad actual
Implementación
 La generación de múltiples unidades actuales se
logra mediante el concepto de macro-expansión
25
Unidades Genéricas

Sea el siguiente subprograma genérico en Ada
generic type T;
procedure Swap(X, Y : in out T) is
Temp : T;
begin
Temp:= X;
X := Y;
Y := Temp;
end;

Aquí,
T
es el parámetro de tipo de los datos
X
e
Y
26
Unidades Genéricas

Producción de tres subprogramas que sólo difieren
en el tipo de sus parámetros
procedure Swapint is new Swap (integer);
procedure Swapreal is new Swap (real);
procedure Swapchar is new Swap (char);
27
Unidades Genéricas

Problema
El código
logical mas(logical in a, logical in b)
{ return a + b; }
retorna la suma (or) de dos valores de tipo logical
a) Efectuar las modificaciones necesarias para que mas se
convierta en unidad genérica
b) Declarar las instancias de producción de cuatro versiones de
mas que permitan sumar valores de tipo logical, integer,
rational y real
28
Unidades Genéricas

Solución
a)
generic type T;
T mas(T in a, T in b)
{ return a + b; }
b)
logical maslogical is new mas(logical);
integer masinteger is new mas(integer);
real masreal is new mas(real);
rational masrational is new mas(rational);
29
Plantillas de funciones


Definición
 Una Plantilla de Función es una unidad formal
utilizada como modelo de producción de una
unidad actual
Implementación
 El compilador genera, de manera automática,
tantas unidades actuales como invocaciones con
diferentes tipos de datos existan
30
Plantillas de funciones

Sea la siguiente plantilla de función en C++
template <class T>
void imprimir(T *V, int k)
{ for(int i=0; i<k; i++)
cout<< V[i] << " ";
cout<< endl;
}

Aquí,
T
es el parámetro de tipo del arreglo
V
31
Plantillas de funciones

Producción de tres unidades actuales a partir de tres
invocaciones con arreglos de distinto tipo base
int main()
{ int a[4] = {1, 2, 3, 4};
float b[6] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6};
char c[5] = "Hola";
imprimir(a, 4);
imprimir(b, 6);
imprimir(c, 5);
return 0;
}
32
Parametrización de subprogramas
33
Códigos como parámetros

El uso de un subprograma como parámetro actual
requiere el envío de



La referencia del segmento de código en RAM, y
La información respecto de su entorno no local
Un subprograma parámetro se puede representar
como un par ordenado de punteros (C, R), donde


C apunta al segmento de código, y
R apunta al registro de activación de la más próxima
unidad perteneciente a su entorno no local
34
Códigos como parámetros
Procedure P...
···
Procedure A...
···
Begin
···
End;
Procedure B(procedure X);
var y: integer;
Procedure C...
···
Begin
···
End;
Begin
X;
B(C);
···
End;
Begin
···
B(A);
···
End
1. P llama a B con el procedimiento A
como parámetro actual
Como B tiene definido un parámetro
formal X, la llamada a X activa el
procedimiento A
2. B se autoinvoca con el procedimiento
C como parámetro actual
Una segunda invocación a X activará
el procedimiento C
35
Códigos como parámetros
Ejercicio
Mostrar las variaciones que presenta el stack
del registros de activación e indicar el valor
finalmente impreso, al ejecutarse el código
int Tres(int k)
{ return(k); }
int Dos(int Y, int j)
{ return(j + Y); }
int Uno(int X, int i)
{ return(i + X); }
void Main()
{ print(Uno(Dos(Tres(3),2),1)); }
Tres:
Dos:
Uno:
k: 3
3
Y: Tres(3)
3 =5
2+ ___
j:2
X: Dos(Tres(3),2)
5 =6
1+ ___
i :1
Main: print(Uno(Dos(Tres(3),2),1))
6
Stack de RA
36