TEMA 6: Abstracción Procedural 6.1 Los subprogramas como abstracciones • Abstracción de procesos • Abstracción de datos Son los mecanismos de abstracción más importantes que puede incluir un LP. • Abstracción: Representación de un objeto que oculta detalles irrelevantes de dicho objeto de modo que consigue hacer más fácil su uso. Los subprogramas los vamos a considerar como abstracciones de unidades de programa que van a estar representados por unidades de representación más simple: • Una sentencia • Una expresión Los programas can a ocultar detalles irrelevantes de los subprogramas. • VENTAJAS: • Las unidades de programa son más simples (más fáciles de leer, escribir y modificar).(La utilización de subprogramas es imprescindible para un diseño descendente) • Las unidades de programa son independientes. Las acciones de un procedimiento son independientes de su uso (el uso de un subprograma es independiente de su implementación). • Las unidades de programa son reutilizables. Se elimina esfuerzo de programación (Un programa deberÃ−a de poder utilizarse en entornos de programación diferentes lo que implica menos mantenimiento) 6.2 Fundamentos de los subprogramas • CaracterÃ−sticas básicas de los subprogramas: • Cada subprograma tiene un solo punto de entrada. • La unidad de programa que realiza la llamada se suspende durante la ejecución del subprograma llamado (en un momento determinado solo existe un programa en ejecución). • El control siempre vuelve a la unidad de programa que realiza la llamada (cuando acaba la ejecución del programa). No todos los procedimientos cumplen estas caracterÃ−sticas, como por ejemplo las subrutinas. 6.2.1 DEFINICIONES BÔSICAS • Subprograma: Es la descripción de las acciones de la abstracción. • Llamada a un subprograma: Es la petición explÃ−cita de la ejecución de un subprograma 1 • Un subprograma está activo si después de ser llamado, ha comenzado la ejecución pero aún no la ha completado (se está ejecutando). • Tipos de subprogramas: • Procedimientos • Funciones • Encabezamiento de los subprogramas: Primera lÃ−nea de la definición de subprograma. Lo que hace es indicar que la unidad sintáctica que sirve es una unidad sintáctica de un tipo. En el encabezamiento de un subprograma se la proporciona un nombre opcional y se incluye una lista de parámetros. Puede servir también como declaración del subprograma • Perfil de parámetros de un subprograma: Es el número, orden y tipo de sus parámetros formales. • En un programa escrito en un lenguaje de alto nivel podemos encontrarnos con: • Definiciones de Subprogramas • Declaraciones de Subprogramas • La definición es la especificación de las acciones que realiza el programa. • La declaración no es más que el encabezamiento del subprograma. El compilador puede tener que traducir la llamada a un subprograma y no haber traducido la definición, pero sÃ− al menos la declaración. Esto es para la comprobación estática de tipos. Ej. ; En C, prototipo de funciones (declaración de subprogramas): proc A B; End Proc B A; End 6.2.2 PARAMETROS • Los subprogramas van a tener dos formas de acceder a los datos que les interesan: • Acceso a variables no locales que tienen que ser visibles desde donde se llama y dentro el subprograma. • Mediante el paso de parámetros (es mucho más flexible al estar construyendo acciones parametrizadas -los datos pueden cambiar en cada una de las llamadas-) • A veces, vamos a necesitar transmitir computaciones, en este caso, hay LP que permiten enviar como parámetro el nombre del subprograma que realiza esa computación. 2 • A los parámetros que aparecen en el encabezamiento de un subprograma se les denomina parámetros formales y no podemos considerarlos variables en un sentido general porque el espacio de vincula a los parámetros formales en el momento de la llamada y la circulación no se realiza de manera directa, sino a través de otras variables, que ya existen en otros ámbitos. • Parámetros actuales: Lista de parámetros que aparecen en la llamada al subprograma y deben vincularse a los parámetros formales. Esta vinculación se realiza dependiendo de la posición que ocupan en la lista: 1º-1º, 2º-2º ... , se habla entonces de parámetros posicionales (cuando la lista de parámetros es corta). Si la lista es larga hay LP que incluyen parámetros clave, en este caso en la llamada al subprograma además del parámetro actual, se incluye el parámetro formal al que debe vincularse. Ej. : Ada Incluir (nom,ap,fnacimiento f,sexo =>s, tiposocio => ts ) • Ventaja: • Podemos colocar los parámetros en cualquier orden. • Desventaja: • El programador debe conocer el nombre de los parámetros formales del subprograma. • Algunos lenguajes de programación permiten parámetros formales que tienen valores por defecto; estos valores se usan si no se pasa en la llamada el parámetro actual correspondiente. Ej. : Ada Procedure (nombre,apellido: cadena;sexo: char; tipo_socio: tsocio:=NUMERARIO; fnacimiento: fecha); • En C: El número de parámetros actuales no tiene que coincidir con el número de parámetros formales. Es responsabilidad del programador que no se produzcan errores 6.2.3. PROCEDIMIENTOS Y FUNCIONES • Los procedimientos son colecciones de sentencias que definen computaciones parametrizadas. Al definir un procedimiento, lo que estamos haciendo es definir una nueva sentencia: ordenar (lista_valores); ¿Qué formas tienen los procedimientos de producir resultados? • Cambiar el valor de las variables no locales • Mediante el paso de parámetros • La llamada a la función se realiza cuando aparece su nombre en una expresión. • El valor producido por la ejecución de la función se devuelve y se reemplaza en la expresión. • Hay funciones que puede producir efectos laterales. 3 Los efectos laterales se producen: • Cuando cambian de valor de alguna variable declarada fuera de la función (variable no local). • Modifican el valor de los parámetros que se le envÃ−an a la función. • Si no se producen efectos laterales, el único efecto que se produce es el valor que devuelve. • Definir nuevos operadores • Definir función potencia • potencia(base, exponente). En la mayorÃ−a de los lenguajes de programación se dispone de ambos tipos. En C solo hay funciones, pero se pueden definir funciones que no devuelven ningún valor: tipo void (manera de declarar el procedimiento). 6.3 Métodos de Paso de Parámetros • Son las formas en que los parámetros se tramiten a los subprogramas Y/O desde los programas. 6.3.1 MODELOS SEMANTICOS DE PASO DE PARAMETROS • Modo de entrada: los parámetros formales del subprograma llamado pueden recibir datos de los de los correspondientes parámetros actuales. • Modo de salida: Los parámetros formales pueden transmitir datos a los parámetros actuales de la llamada al subprograma. • Modo de entrada salida: pueden ocurrir ambas cosas. Hay dos modelos conceptuales que indican como se realiza la transferencia: • Moviendo fÃ−sicamente el valor (operación de copia) • Transmitiendo un camino de acceso (se transmiten normalmente un apuntador a esa variable). 6.3.2 MODOS DE IMPLEMENTACIà N DEL PASO DE PARAMETROS • Paso por valor(E) El valor del parámetro actual se usa para inicializar el valor del parámetro formal correspondiente, y este parámetro forma la actual del subprograma como una variable local. Es una implementación del modelo semántico: modo de entrada. • La transferencia se realiza normalmente mediante movimiento fÃ−sico del valor porque conlleva un acceso más eficiente del mismo (Se copia el valor dentro del ámbito donde se va a utilizar). También podrÃ−a implementarse transmitiendo un camino de acceso siempre que el subprograma no modifique el valor del parámetro. • Desventajas: • Requiere almacenamiento adicional. • Si el parámetro que se está enviando es un objeto grande lleva un tiempo adicional además de un coste en el almacenamiento. • Ventaja: 4 • La eficiencia en el acceso al valor almacenado en el parámetro formal. • Paso por resultado: Es una implementación del modelo semántico: modelo de salida. En este caso desde la unidad del programa que realiza la llamada no se transmite y ningún valor al subprograma. • El parámetro formal va a actuar en el subprograma como una variable local. La única diferencia es que justo antes de que se devuelva el control a la unidad del programa que realiza la llamada el valor del parámetro formal, se pasa ( copia) al parámetro actual. Este parámetro actual debe de ser una variable (no puede ser una constante). • Implementación del Paso por resultado: • Mediante una operación de copia (movimiento fÃ−sico del valor). Es la solución tÃ−pica que utilizan los LP que usan este mecanismo de paso. Sus Inconvenientes es que: • Se requiere almacenamiento adicional • Costo de tiempo • Enviando un camino de acceso: Debemos asegurarnos que el valor inicial del parámetro actual no se use en el subprograma llamado. • Los problemas que plantea el mecanismo de Paso por resultado son: • Colisión del parámetro actual: Sub (i,i): Lo normal es que los parámetros formales correspondientes a estos parámetros actuales tengan nombre. Cuando finaliza ese procedimiento se van a intentar transferir esos valores a los parámetros actuales. El valor de “i” va a depender del orden de evaluación. • El implementador puede elegir dos maneras diferentes para la evaluación de las direcciones de los parámetros actuales: momento de la llamada y momento de retorno. El subprograma en el momento de la llamada no necesita haber evaluado la dirección del programa. Sub1(lista[indice]; • Dependiendo del momento en que se evalúe puede tener valores diferentes. • Puede ser que “Ã−ndice” sea una variable no local accesible por el subprograma sub1, con lo cual el valor del Ã−ndice puede cambiar. • En ambos casos se trata del problema de portabilidad, porque si en la definición del lenguaje que no se especifica al orden de evaluación, se pueden dar resultados diferentes según que compilador utilicemos. • Paso por Valor-Resultado o Paso por Copia: Se trata de un mecanismo de implementación para el modelo semántico: modo de E-S. Es una combinación de paso por valor y del paso por resultado. También se llama paso por copia porque en el momento en que la llamada se copia el valor del parámetro actual en el parámetro formal. Tiene los inconvenientes que dijimos para los anteriores (costoso en espacio y tiempo), y tiene el problema de la portabilidad (orden en que se evalúan los parámetros de la lista). • Paso Por Referencia: Forma de implementación del modo de E/S. En este caso se transmite un camino de acceso al subprograma. Normalmente el camino de acceso que se transmite es una dirección (la dirección de la celda que almacena al parámetro actual). • Ventajas: 5 • El proceso del paso de parámetro es eficiente tanto en tiempo como en espacio. • Desventajas: • El acceso al parámetro formal es más lento (se necesita un nivel más de indirección). • Creación de alias (nombres que utilizan la misma celda de memoria). Ej. : procedure p(var x,y: integer) Si la llamada es de la forma: p(i,i); entonces “x” e “y” son alias; Existen otras formas de crear alias: • p(lista[i],lista[j]); si i=j entonces en el momento en que se llama al subprograma “x” e ”y” son alias. • Procedure p2 (lista[i],lista); • Procedure mayor Var global: integer; Procedure menor (var local: integer) Begin ........ End; Begin ......... menor (global); ......... End; • Paso por Nombre: Es una implementación del modo de entrada salida. Consiste la sustitución textual de todas las operaciones de los parámetros formales en el subprograma por los correspondientes parámetros actuales. El objetivo de este modo de implementación es muy flexible. Atendiendo a la entidad de los parámetros actuales vamos a estudiar las diferencias del paso por nombre con los demás: • Si el parámetro actual es una variable escalar el paso por nombres equivalente al paso por referencia. • Si es una expresión constante: el paso por nombres equivalente al paso por valor. • Si es un elemento de un array: el paso por nombre es distinto a todos los anteriores ya que puede suceder que la expresión Ã−ndice cambie dentro del subprograma. • Si es una expresión que contiene referencias a variables - (2*i+j)- : Como la sustitución es textual (el parámetro formal se evalúa en cada subexpresión), el paso por nombre no es igual a ninguno de los otros modos de implementación del paso de parámetros. 6 Ej.: ...... Var Elemento: integer; A: array [1..2] of integer; Procedure sub (x:integer;) Begin A[1]:=6; Elemento:=2; x:=x+3; end; begin A[1]:=1; A[2]:=2; Elemento:=1; sub(a[Elemento]); //Vamos a estudiar el efecto de esta llamada ..... End; Mecanismo A[1] Paso por Nombre 6 Paso por Valor-Resultado 4 Paso por referencia 9 Paso por Nombre 6 6.4 Subprogramas como parametros A[2] 2 2 2 5 Elemento 2 2 2 5 • A la hora de hacer esto, lo que vamos a necesitar es una descripción de los parámetros del subprograma (además de necesitar código). Para que compilador pueda realizar una comprobación estática de tipos. Ej.: (Pascal) Function integrar (function fun (x:real):real;lim_inf,lim_sup:real):real; 7 Var valfun:real; begin ....... valfun:=fun(lim_inf); ........ End; En C no se pasan los nombres funciones, sino lo que se hace pasar punteros a funciones. El tipo de esos punteros a funciones es el “perfil de la función”. Subprogramas sobrecargados 6.5 • Hay operadores sobrecargada (operadores que tiene varios significados). El significado salto de un operador sobre carga . Ada Generic Type item is private; Procedure inter-generico (x,y in out item); Procedure inter-generico (x,y in out item); s T:item; Begin T:=x; x:=y;y:=t; End; • Para usar ese tipo genérico hay que cambiar los valores de tipo entero: procedure inter is new inter-generico(integer); AquÃ− se genera código intermedio -se instancia item como integer-. Puedo hacer otra instancia: procedure inter is new inter-generico(float); • Inter(i,j); Si i,j son enteros llama al subprograma que actúa como enteros. Si son reales llama al que actúa con reales. Es el compilador el que genera el código necesario a instancias del programador. Ej.Procedure tratar_datos () Procedure ordenar (lista_reales: in out vector real; 8 Lim_inf: in integer; Lim_sup: in integer) IS End ordenar Procedure ordenar (lista_enteros: in out vector ineteger Lim_inf: in integer; Lim_sup: in integer) IS End ordenar Subprogramas polimorficos 6.6 • Una manera de incrementar la reusabilidad del SW serÃ−a evitar situaciones donde se repita el código de dos funciones sobrecargadas, para evitar esto hay LP que permiten definir subprogramas polimórficos o genéricos: subprograma que tiene parámetros de tipos diferentes en activaciones diferentes. • Los subprogramas sobrecargados pueden verse como un tipo de polimorfismo (polimorfismo ad hoc : subpragramas sobrecargados ). • El polimorfismo es paramétrico si en los parámetros del subprograma aparecen que utilizan programas genéricos. f:[a] - a <- En La definición de parámetros formales aparecen parámetros genéricos • Ada proporciona un mecanismo de polimorfismo en tiempo de compilación. Por ej. generic type item is private procedure inter-generico (x,y:in out item); procedure inrter-genérico (x,y:in out item); t:item begin t:=x; x:=y; y:=t; end inter-generico • El compilador no genera código para el procedimineto intergenérico se hacen instancias. • Para usar ese tipo genérico: cambia valores de tipo entero: 9 Procedure inter is new inter_generico (integer); |--------- en éste momento el compilador generá el código. Tema 6: Abstracción Procedural LPR 1 10 10