Este sitio web usa cookies de terceros para analizar el tráfico y personalizar los anuncios. Si no está de acuerdo, abandone el sitio y no siga navegando por él. ×


6.4. Modificación de parámetros

Ya habíamos visto qué son los parámetros: una serie de datos extra, que indicábamos entre paréntesis en la cabecera de un procedimiento o función.

Es algo que estamos usando, casi sin darnos cuenta, desde el primer apartado del curso, cuando empezamos a usar "WriteLn":

writeLn( 'Hola' );

Esta línea es una llamada al procedimiento "WriteLn", y como parámetros le estamos indicando lo que queremos que escriba, en este caso, el texto "Hola".

Pero vamos a ver qué ocurre si modificamos un parámetro:

(* PROCMOD1.PAS, Procedimiento que modifica parametros *)
(* Primer intento: paso por valor                      *)
(* Parte de CUPAS5, por Nacho Cabanes                  *)
 
program ModificarParametros1;

var dato: integer;

procedure modifica( variable : integer);
begin
    variable := 3 ;
    writeLn( 'Dentro: ', variable );
end;

begin
    dato := 2;
    writeLn( 'Antes: ', dato );
    modifica( dato );
    writeLn( 'Después: ', dato );
end. 

¿Qué podemos esperar que pase? Vamos a ir siguiendo cada instrucción:

Pues no es eso lo que ocurre: escribe un 2. Las modificaciones que hagamos a "dato" dentro del procedimiento "modifica" sólo son válidas mientras estemos dentro de ese procedimiento (lo que realmente ocurre es que el procedimiento está recibiendo una copia de la variable, de modo que si hacemos algún cambio, éstos no se cambios no afectan a la variable original, que existe fuera del procedimiento).

Eso es pasar un parámetro por valor: podemos leer su valor, pero no podemos alterarlo (los cambios se pierden al salir).

La alternativa es "pasar parámetros por referencia, añadiendo la palabra "var" delante de cada parámetro que sea modificable dentro del procedimiento (o función):

(* PROCMOD2.PAS, Procedimiento que modifica parametros *)
(* Segundo intento: paso por referencia                *)
(* Parte de CUPAS5, por Nacho Cabanes                  *)
 
program ModificarParametros2;

var dato: integer;

procedure modifica( var variable : integer);
begin
    variable := 3 ;
    writeLn( 'Dentro: ', variable );
end;

begin
    dato := 2;
    writeLn( 'Antes: ', dato );
    modifica( dato );
    writeLn( 'Después: ', dato );
end.

Esta vez la última línea del programa sí que escribe un 3 y no un 2, porque hemos permitido que los cambios hechos a la variable salgan del procedimiento (para eso hemos añadido la palabra "var").

El nombre "referencia" alude a que no se pasa realmente al procedimiento o función el valor de la variable, sino la dirección de memoria en la que se encuentra, algo que más adelante llamaremos un "puntero".

Una de las aplicaciones más habituales de pasar parámetros por referencia es cuando debemos devolver más de un valor: habíamos visto que una función era muy parecida a un procedimiento, pero además devolvía un valor (pero sólo uno); cuando necesitamos obtener más de un valor de salida, la forma habitual de conseguirlo es pasándolos como parámetros por referencia, (precedidos por la palabra "var"). Existe alguna otra alternativa menos elegante, como devolver un array, cosas que no tiene mucho sentido si no se trata de datos relacionados..

Otra aplicación puede ser optimizar (ligeramente) velocidad: si pasamos datos de gran tamaño, será algo más lento pasarlos por valor (hay que duplicar toda su estructura) que pasarlos por referencia (sólo se pasa su dirección), pero este tipo de consideraciones hay que tenerlas más adelante, no en la primera implementación del programa, porque tratar de optimizar velocidad antes de tener la certeza de que todo funciona correctamente puede dar lugar a errores difíciles de detectar.

¿Y si la variable tiene el mismo nombre en la función y en el cuerpo del programa? ¿Conseguiremos "engañar" al compilador y modificar su valor sin necesidad de usar "var"?

(* PROCMOD3.PAS, Procedimiento que modifica parametros *)
(* Tercer intento: paso por valor de variables con el  *)
(*     el mismo nombre                                 *)
(* Parte de CUPAS5, por Nacho Cabanes                  *)
 
program ModificarParametros3;

var dato: integer;

procedure modifica( dato : integer);
begin
    dato := 3 ;
    writeLn( 'Dentro: ', dato );
end;

begin
    dato := 2;
    writeLn( 'Antes: ', dato );
    modifica( dato );
    writeLn( 'Después: ', dato );
end.

Como se ve en este ejemplo, da igual el nombre que tengan las variables. El comportamiento será el mismo: ambas variables son distintas, aunque el nombre parezca indicar lo contrario.

Ejercicio propuesto 6.4.1: Crea un procedimiento "Intercambia", que intercambie el valor de los dos números enteros que se le indiquen como parámetro.
Ejercicio propuesto 6.4.2: Crea un procedimiento "ObtenerIniciales", que reciba una cadena como "Nacho Cabanes" y devuelva las letras N y C (primera letra, y letra situada tras el primer espacio), usando parámetros por referencia.
Ejercicio propuesto 6.4.3: Crea un procedimiento "ResolverEcuacionCuadratica", que resuelva una ecuación de segundo grado en la forma y=ax2+bx+c. Recibirá como parámetros por valor a, b, y c, y devolverá las dos soluciones x1 y x2 (suponiendo que tenga dos soluciones reales) como parámetros por referencia.