9 Subalgortimos
Un principio fundamental en la resolución de un problema es intentar descomponerlo en partes más pequeñas, que puedan ser más fáciles de afrontar. Este concepto también se aplica en la programación. Nuestros algoritmos pueden descomponerse en subalgoritmos que den solución a un aspecto del problema, de menor extensión. Este proceso se conoce como descomposición algorítmica o descomposición modular. Cada subalgoritmo debe ser independiente de los demás y a su vez podría seguir descomponiéndose en partes más sencillas en lo que se conoce como refinamiento sucesivo. Si un programa es muy largo se corre el riesgo de que sea muy difícil de entender como un todo, pero siempre se lo puede dividir en secciones más simples y manejables. Un subalgoritmo se escribe una vez y luego es utilizado por todos aquellos algoritmos que lo necesiten.
Observemos el siguiente ejemplo, que presenta un algoritmo para el cálculo de un número combinatorio. Recordemos que el número combinatorio entre \(n\) y \(k\) se define como:
\[ {n \choose k} = \frac{n!}{(n-k)!k!} \hspace{1cm} k \le n, k \in \mathbb{N}_0, n \in \mathbb{N}\]
ALGORITMO: Ej 1. Cálculo de números combinatorios
COMENZAR
VARIABLE numerica n, k, fact1, fact2, fact3, comb
LEER n, k \\ Asumimos que n y k cumplen con los requisitos
\\ Calcular el factorial de n
fact1 <- 1
PARA i DESDE 1 HASTA n HACER
fact1 <- fact1 * i
FIN PARA
\\ Calcular el factorial de n-k
fact2 <- 1
PARA i DESDE 1 HASTA n - k HACER
fact2 <- fact2 * i
FIN PARA
\\ Calcular el factorial de k
fact3 <- 1
PARA i DESDE 1 HASTA k HACER
fact3 <- fact3 * i
FIN PARA
\\ Calcular el nro combinatorio
comb <- fact1 / (fact2 * fact3)
ESCRIBIR "El nro combinatorio de " n " tomado de a " k " es " comb
FIN
Como se puede observar, el cálculo del factorial requiere siempre la misma estructura y se repite tres veces. Esto constituye una parte del problema cuya resolución puede plantearse por separado, dando lugar a un subalgoritmo. El algoritmo quedaría mejor expresado de la siguiente manera:
ALGORITMO: Ej 2. Cálculo de números combinatorios
COMENZAR
VARIABLE numérica n, k, comb
LEER n, k
comb <- factorial(n) / (factorial(n - k) * factorial(k))
ESCRIBIR "El nro combinatorio de " n " tomado de a " k " es " comb
FIN
Aquí se puede ver cómo se simplificó la estructura del algoritmo, al hacer uso de un subalgoritmo llamado factorial
que toma entre paréntesis un valor para el que procede a calcular y devolver el factorial. Para que esto funcione, debemos definir aparte dicho subalgoritmo, como se muestra a continuación. Más adelante veremos los detalles de esta definición y por qué, en particular, se dice que este subalgoritmo es una función:
FUNCIÓN factorial(n: numérico): numérico
VARIABLE numérica fact
fact <- 1
PARA i DESDE 1 HASTA n HACER
fact <- fact * i
FIN PARA
DEVOLVER fact
FIN FUNCIÓN
El empleo de subalgoritmos, desarrollando por separado ciertas partes del problema, resulta especialmente ventajoso en los casos siguientes:
- En algoritmos complejos: si el algoritmo, y luego el programa, se escribe todo seguido resulta muy complicado de entender, porque se pierde la visión de su estructura global dada la gran cantidad de operaciones que lo conforman. Aislando ciertas partes como subalgoritmos separados se reduce la complejidad.
- Cuando se repiten operaciones análogas: si la resolución de un problema requiere realizar una tarea que se repite varias veces en el algoritmo, podemos definir dicha tarea como un subalgoritmo por separado. De esta manera, su código se escribirá sólo una vez aunque se use en muchos puntos del programa.
Los subalgoritmos se clasifican en funciones y procedimientos. Las funciones devuelven como resultado un solo valor al algoritmo principal. Los procedimientos, en cambio, pueden devolver cero, uno o varios valores.
9.1 Funciones
Una función es un subalgoritmo que devuelve un único resultado. Ya hemos trabajado con funciones que asumimos predefinidas, como por ejemplo las funciones módulo (MOD
), valor absoluto (ABS
) o raiz cuadrada (RAIZ
), pero ahora veremos que podemos definir nuestras propias funciones. El valor que la función devuelve como resultado define su tipo, de modo que una función puede ser de tipo numérica, caracter o lógica. En programación, la noción de función se asemeja a la idea matemática de función de una o más variables. Por ejemplo, podemos pensar en la función \(f(x, y) = x^2 + 3y\). En pseudocódigo, el subalgoritmo que se encargaría de implementarla es:
FUNCIÓN f(x: numérico, y: numérico): numérico
COMENZAR
DEVOLVER x ** 2 + 3 * y
FIN FUNCIÓN
Dado que esta función devuelve un valor numérico, decimos que la misma es de tipo numérico, lo cual se indica al final del encabezado. Se dice que \(x\) e \(y\) son los parámetros formales o ficticios y son los que permiten expresar la “ley” o “forma” de la función. También se aclara en el encabezado que estos parámetros son de tipo numérico. Los valores en los cuales se quiere evaluar la función se llaman parámetros actuales o reales. Por ejemplo, si nos interesa calcular \(f(4, 5)\), los valores \(4\) y \(5\) son los parámetros actuales y se establece una correspondencia entre el parámetro formal \(x\) y el real \(4\), así como entre la \(y\) y el \(5\). Como veremos más adelante, dicha correspondencia puede establecerse de distintas formas. En este ejemplo, el resultado que se obtiene es \(31\). A los parámetros también se les dice argumentos.
También puede ser expresada como:
FUNCIÓN f(x: numérico, y: numérico): numérico
COMENZAR
VARIABLE numérica rtdo
rtdo <- x ** 2 + 3 * y
DEVOLVER rtdo
FIN FUNCIÓN
De manera general, la definición de una función es:
FUNCIÓN nombre(lista de parámetros formales): tipo de resultado
COMENZAR
Declaración de variables
Acciones
DEVOLVER valor
FIN FUNCIÓN
La palabra clave DEVOLVER
provoca la inmediata finalización de la ejecución de la función e indica cuál es el resultado de la misma, cuyo tipo debe coincidir con el tipo de función declarado antes. La acción DEVOLVER
se puede insertar en cualquier punto de la parte ejecutable de la función y además es posible utilizar más de una sentencia DEVOLVER
en una misma función, aunque sólo una llegue a ejecutarse. Esto puede verse en el siguiente ejemplo:
FUNCIÓN maximo(num1: numérico, num2: numérico): numérico
COMENZAR
SI num1 >= num2
ENTONCES
DEVOLVER num1
SI NO
DEVOLVER num2
FIN SI
FIN FUNCIÓN
Para usar una función en un algoritmo, se la invoca escribiendo su nombre seguida por los valores actuales entre paréntesis, separados por coma. Esta invocación representa un valor del tipo de la función que puede ser usado como operando en otra expresión. Al invocar una función es obligatorio que los valores suministrados para los argumentos reales correspondan en cantidad, tipo y orden con los argumentos formales de la definición de la función. Por ejemplo:
ALGORITMO: Ej 3. Hallar el máximo entre dos valores
COMENZAR
ESCRIBIR "El máximo entre 5 y 10 es " maximo(5, 10)
FIN
O más general:
ALGORITMO: Ej 3. Hallar el máximo entre dos valores
COMENZAR
VARIABLE numérica x, y
LEER x, y
ESCRIBIR "El máximo es " maximo(x, y)
FIN
9.2 Procedimientos
Un procedimiento es un subalgoritmo que agrupa una acción o conjunto de acciones, dándoles un nombre por el que se las puede identificar posteriormente. Se diferencia de la función en que no tiene como objetivo, en general, devolver un valor, pudiendo devolver ninguno, uno o varios. Esto quiere decir que tampoco se declara de qué tipo es. El objetivo principal de los procedimientos es ayudar en la modularidad del programa y evitar la repetición de acciones.
Como en las funciones, desde el algoritmo principal se pasan valores al procedimiento utilizando parámetros o argumentos, aunque también puede haber procedimientos que carezcan de los mismos. Para usar un procedimiento hay que invocarlo, escribiendo su nombre y a continuación, si los hay, los valores de los argumentos actuales para esa llamada, separados por comas. Aquí también los argumentos reales deben ser compatibles en cuanto a la cantidad, tipo y orden que los argumentos formales declarados en la definición del procedimiento.
Por ejemplo, podemos definir un procedimiento que se encargue de escribir un título para la salida de nuestro algoritmo y otro para escribir una línea que separe los resultados:
ALGORITMO: Ej 4. Procedimientos con y sin argumentos
COMENZAR
...
colocarTitulo("Primer grupo de resultados")
ESCRIBIR 1
colocarLinea()
ESCRIBIR 2
colocarLinea()
ESCRIBIR 3
colocarTitulo("Segundo grupo de resultados")
ESCRIBIR 4
colocarLinea()
ESCRIBIR 5
colocarLinea()
ESCRIBIR 6
FIN
PROCEDIMIENTO colocarTitulo(titulo: caracter)
ESCRIBIR "================================="
ESCRIBIR titulo
ESCRIBIR "================================="
FIN PROCEDIMIENTO
PROCEDIMIENTO colocarLinea()
ESCRIBIR "_________________________________"
FIN PROCEDIMIENTO
Como resultado la salida mostrará:
=================================
Primer grupo de resultados
=================================
1
_________________________________
2
_________________________________
3
=================================
Segundo grupo de resultados
=================================
4
_________________________________
5
_________________________________
6
_________________________________
En el siguiente ejemplo podemos identificar los argumentos reales a
(con el valor 5), b
(con el valor 2), c
y d
(sin valores asignados inicialmente). Cuando el procedimiento proced1
es invocado, se establece una correspondencia con los argumentos formales n1
, n2
, n3
y n4
, respectivamente. n1
toma el valor 5, n2
toma el valor 2 y el procedimiento le asigna los valores 7 a n3
y 1 a n4
. Al finalizar, este procedimiento habrá dejado sin cambios a las variables a
y b
, mientras que le habrá asignado los valores 7 a c
y 1 a d
. Como resultado, el algoritmo escribe “5 2 7 1”.
ALGORITMO: Ejemplo 5
COMENZAR
VARIABLE numérica a, b, c, d
a <- 5
b <- 2
proced1(a, b, c, d)
ESCRIBIR a b c d
FIN
PROCEDIMIENTO proced1(n1: numérico, n2: numérico, n3: numérico, n4: numérico)
n3 <- n1 + n2
n4 <- n2 - 1
FIN PROCEDIMIENTO
En el siguiente ejemplo, el procedimiento proced2
modifica las variables que actúan como argumentos reales. Al ser invocado, se establece una correspondencia entre los argumentos reales a
(con el valor 5) y b
(con el valor 2), y los argumentos formales n1
y n2
, respectivamente. De esta forma, la primera acción del procedimiento le asigna el valor 7 a n1
y 1 a n2
. De esta manera, al finalizar a
vale 7 y b
vale 1 y el algoritmo escribe “7 1”.
ALGORITMO: Ejemplo 6
COMENZAR
VARIABLE numérica a, b
a <- 5
b <- 2
proced2(a, b)
ESCRIBIR a b
FIN
PROCEDIMIENTO proced2(n1: numérico, n2: numérico)
n1 <- n1 + n2
n2 <- n2 - 1
FIN PROCEDIMIENTO
9.3 Pasaje de argumentos
Los algoritmos y subalgoritmos comunican información entre sí a través de los parámetros o argumentos y existen distintas formas de realizar esta comunicación.
9.3.1 Pasaje por valor
En este caso, los argumentos representan valores que se transmiten desde el algoritmo hacia el subalgoritmo. Las funciones, además, cuentan con un valor de retorno, que es el valor que se transmite desde el subalgoritmo hacia el algorimo que lo llamó.
El pasaje por valor implica que los objetos del algoritmo provistos como argumentos en la llamada al subalgoritmo no serán modificados por la ejecución del mismo. Este sistema funciona de la siguiente forma:
- Se evalúan los argumentos reales usados en la llamada.
- Los valores obtenidos se copian en los argumentos formales dentro del subalgoritmo.
- Los argumentos formales se usan como variables dentro del subalgoritmo. Aunque los mismos sean modificados (por ejemplo, se les asignen otros valores), no se modifican los argumentos reales en el algoritmo, sólo sus copias dentro del subalgoritmo.
En general, se desalienta la reasignación de valor a un argumento pasado por valor por resultar confuso.
9.3.2 Pasaje por referencia
En otras situaciones es deseable que el subalgoritmo pueda modificar las variables del algoritmo que se usen como argumentos. De esta manera se puede producir más de un resultado. De esto se encarga el pasaje por referencia. Si un parámetro se pasa por referencia, esta variable será empleada en el subalgoritmo como si fuera suya, es decir, las modificaciones que sufra dentro del subalgoritmo la modificarán permanentemente. Este sistema funciona de la siguiente forma:
- Se seleccionan las variables usadas como argumentos reales.
- Se asocia cada variable con el argumento formal correspondiente.
- Los cambios que experimenten los argumentos formales se reflejan también en los argumentos reales de origen.
9.3.3 Ejemplos
Algunos lenguajes de programación permiten que el programador elija el modo en el que se realiza el pasaje. En el siguiente ejemplo veremos la diferencia entre ambos modos.
ALGORITMO: Ejemplo 7
COMENZAR
VARIABLE numérica a, b, c
a <- 3
b <- 5
c <- fun(a, b - a)
ESCRIBIR a b c
FIN
FUNCIÓN fun(x: numérico, y: numérico): numérico
x <- x + 1
DEVOLVER x + y
FIN FUNCIÓN
Si el pasaje de argumentos se hace por valor, los cambios producidos en el cuerpo de la función sobre los parámetros formales no son transmitidos a los parámetros actuales. Esto significa que los formales son una “copia” de los actuales. Los pasos que sigue el algoritmo son:
a = 3, b = 5
- Al invocar la función:
x = 3, y = 5 - 3 = 2
- Primera línea de la función:
x = 3 + 1 = 4
- La función devuelve el valor
x + y = 4 + 2 = 6
- De regreso en el algoritmo principal:
c
recibe el valor6
- Se escribe:
3 5 6
Si el pasaje de argumentos se hace por referencia, cualquier modificación realizada sobre los parámetros formales es automáticamente realizada también a los actuales. Los pasos que sigue el algoritmo son:
a = 3, b = 5
- Al invocar la función:
x = 3, y = 5 - 3 = 2
- Primera línea de la función:
x = 3 + 1 = 4
. El parámetro actual asociado conx
,a
, sufre el mismo cambio y recibe el valor4
(a = 4
). - La función devuelve el valor
x + y = 4 + 2 = 6
- De regreso en el algoritmo principal:
c
recibe el valor6
- Se escribe:
4 5 6
Analicemos ahora el tipo de pasaje en el contexto de un procedimiento:
ALGORITMO: Ejemplo 8
COMENZAR
VARIABLE numérica a, b
a <- 8
b <- 4
miProc(a, b)
ESCRIBIR a b
FIN
PROCEDIMIENTO miProc(x: numérico, y: numérico)
x <- x * 2
y <- x - y
FIN PROCEDIMIENTO
Si el pasaje es por referencias, los pasos que sigue el algoritmo serían:
a = 8, b = 4
- Al invocar la función:
x = 8, y = 4
- Primera línea de la función:
x = 8 * 2 = 16
. Lo mismo sucede con el parámetro actuala
:a = 16
. - Segunda línea de la función:
y = 16 - 4 = 12
. Lo mismo sucede con el parámetro actualb
:b = 12
. - Al regresar al algoritmo principal, la sentencia
ESCRIBIR
produce:16 12
.
Si el pasaje hubiese sido por valor, a
y b
no hubiesen cambiado y la sentencia ESCRIBIR
mostraría 8, 4
. Como en un procedimiento los resultados regresan en los mismos parámetros, no pueden ser todos pasados por valor, porque en ese caso el procedimiento nunca realizaría ninguna acción.
Si el parámetro x
se pasa por valor mientras que y
se pasa por referencia, los pasos serían:
a = 8, b = 4
- Al invocar la función:
x = 8, y = 4
- Primera línea de la función:
x = 8 * 2 = 16
. - Segunda línea de la función:
y = 16 - 4 = 12
. Lo mismo sucede con el parámetro actualb
:b = 12
. - Al regresar al algoritmo principal, la sentencia
ESCRIBIR
produce:8 12
.
9.4 Variables locales y globales
Como ya sabemos, en los algoritmos definimos variables que son de ayuda para la resolución de los problemas. De la misma forma, también se pueden definir variables dentro de los subalgoritmos. Por esta razón, podemos distinguir entre variables locales y globales, haciendo referencia a cuál es su alcance o en qué ámbito existen:
- Variable local: es aquella que está declarada dentro de un subalgoritmo, en el sentido de que “existe” dentro de ese subalgoritmo. No tiene nada que ver con las variables que puedan ser declaradas con el mismo nombre en cualquier parte del algoritmo principal o de otros subalgoritmos. Cuando otro subalgoritmo utiliza el mismo nombre se refiere a una posición diferente en memoria.
- Variable global: es aquella que está declarada en el algoritmo principal. Es accesible para todos los subalgoritmos que de él dependen, sin ser pasada como argumento.
La parte del algoritmo en que una variable se define se conoce como ámbito (scope, en inglés).
El uso de variables locales tiene muchas ventajas. Las variables locales permiten independizar al subalgoritmo del algoritmo principal. Las variables definidas localmente en un subalgoritmo no son reconocidas fuera de él. La comunicación entre el subalgoritmo y el algoritmo principal se da exclusivamente a través de la lista de parámetros. Esta característica hace posible dividir grandes proyectos en piezas más pequeñas independientes. Cuando diferentes programadores están implicados, pueden trabajar independientemente.
Las variables globales tienen la ventaja de compartir información entre diferentes subalgoritmos y el algoritmo principal sin tener que hacer menciones en la lista de parámetros de los subalgoritmos.
Analicemos el siguiente ejemplo:
ALGORITMO: Ejemplo 9
COMENZAR
VARIABLE GLOBAL numérica z
VARIABLE LOCAL numérica x, y
x <- 2
z <- 10
y <- fcn(x)
ESCRIBIR x z y
FIN
FUNCIÓN fcn(l: numérico): numérico
VARIABLE GLOBAL numérica z
VARIABLE LOCAL numérica x
z <- 5
x <- 7
DEVOLVER l + 4
FIN FUNCIÓN
z
es una variable global, es decir, puede ser accedida desde el algoritmo o desde la función. x
es el nombre con el que se indican dos variables. Una es local al algoritmo principal y, por lo tanto, puede ser accedida sólo desde él. La otra es local a la función.
Cuando se realiza la ejecución de este algoritmo, se dan los siguientes pasos:
x
recibe el valor 2z
recibe el valor 10se llama a la función y se establece la correspondencia entre el parámetro formal
l
y el actualx
(l
= 2) y se ejecuta la función:- la variable global
z
toma el valor 5 (deja de valer 10) - la variable local
x
toma el valor 7, pero lax
del algoritmo principal no se modifica, siguen con valor 2. - se devuelve el valor 2 + 4 = 6
- la variable global
de regreso en el algoritmo principal,
y
recibe el valor 6se escribe “2 5 6”, es decir, los valores de
x
,z
ey
9.4.1 Transparencia referencial
Como ya hemos mencionado, cuando se escribe un algoritmo o un programa siempre debe buscarse mantener cierta claridad. En lo que respecta a los subalgoritmos, un principio deseable de claridad se denomina transparencia referencial, que se logra cuando el subalgoritmo sólo utiliza elementos mencionados en la lista de argumentos o definidos localmente, sin variables globales. Esto garantiza que, cada vez que se la invoque con los mismos valores en los argumentos de entrada, el subalgoritmo produzca el mismo resultado.
El uso de variables globales permite escribir subalgoritmos que carecen de transparencia referencial. Si un subalgoritmo modifica alguna variable externa, se dice que produce efectos secundarios, debe realizarse con precaución y generalmente es desaconsejable.
9.5 Código en IML de los ejemplos vistos
/* Crear una librería en mi computadora */
libname subalg "C:\direccion\hasta\una\carpeta";
/*
Observaciones:
- En su definción, las funciones deben hacer uso de la sentencia "return",
los procedimientos no.
- En su invocación, los procedimientos se corren usando run nombreProc(...);
o call nombreProc(...); pero las funciones se corren directo sin usar call o run.
- Cuando definimos los módulos, hay que decir dónde se guardarán (con "reset"). Yo los voy a
guardar dentro de la librería creada arriba "subalg", en un tipo especial de archivo
de SAS llamado "catálogo". Al catálogo le puedo poner cualquier nombre, en este caso, "ejemplos";
- Después de crear el/los módulo/s, debo guardarlos. Puedo guardarlos todos juntos si están
dentro del mismo proc iml con store module = _all_ o uno por uno con store module = nombreDelModulo;
- SAS IML usa PASAJE POR REFERENCIA!!!! Cuidado!!! Todo lo que se haga dentro del módulo
modifican los respectivos objetos del programa principal.
*/
/* Definir todos los módulos (subalgoritmos) que usaré en un mismo proc */
proc iml;
reset storage = subalg.ejemplos;
* Ej 2. Función factorial;
start factorial(n);
fact = 1;
do i = 1 to n;
fact = fact * i;
end;
return fact;
finish factorial;
* Ej 3. Función maximo;
start maximo(num1, num2);
if num1 >= num2 then return num1;
else return num2;
finish maximo;
* Ej 4. Procedimiento colocarTitulo;
start colocarTitulo(titulo);
print "=================================";
print titulo;
print "=================================";
finish colocarTitulo;
* Ej 4. Procedimiento colocarLinea;
start colocarLinea;
print "_________________________________";
finish colocarLinea;
* Ej 5. Procedimiento proced1;
start proced1(n1, n2, n3, n4);
n3 = n1 + n2;
n4 = n2 - 1;
finish proced1;
* Ej 6. Procedimiento proced1;
start proced2(n1, n2);
n1 = n1 + n2;
n2 = n2 - 1;
finish proced2;
* Ej 7. Pasaje por referencia en una función;
start fun(x, y);
x = x + 1;
return x + y;
finish fun;
* Ej 8. Pasaje por referencia en un procedimiento;
start miProc(x, y);
x = x * 2;
y = x - y;
finish miProc;
* Ej 9. Variables globales;
start fcn(l) global(z);
z = 5;
x = 7;
return l + 4;
finish fcn;
store module = _all_;
quit;
/* Ej 1. Cálculo de números combinatorios (sin subalgoritmos) */
proc iml;
n = 10;
k = 2;
fact1 = 1;
do i = 1 to n;
fact1 = fact1 * i;
end;
fact2 = 1;
do i = 1 to n - k;
fact2 = fact2 * i;
end;
fact3 = 1;
do i = 1 to k;
fact3 = fact3 * i;
end;
comb = fact1 / (fact2 * fact3);
print "El nro combinatorio de " n " tomado de " k " es " comb;
quit;
/* Ej 2. Cálculo de números combinatorios (con subalgoritmos) */
proc iml;
reset storage = subalg.ejemplos;
load module = factorial; * Esta línea no es necesaria;
n = 10;
k = 2;
comb = factorial(n) / (factorial(n - k) * factorial(k));
print "El nro combinatorio de " n " tomado de " k " es " comb;
quit;
/* Ej 3. Hallar el máximo entre dos valores */
proc iml;
reset storage = subalg.ejemplos;
a = 5;
b = 10;
c = 2;
d = -1;
print "El maximo entre " a " y " b " es " (maximo(a, b));
print "El maximo entre " b " y " c " es " (maximo(b, c));
print "El maximo entre " c " y " c " es " (maximo(c, c));
print "El maximo entre " d " y " c " es " (maximo(d, c));
quit;
/* Ej 4. Procedimientos para colocar títulos o líneas */
* Se ve mejor en el output (sólo caracteres) que en el Results Viewer (ya tiene formato);
proc iml;
reset storage = subalg.ejemplos;
* Cualquier cosa para mostrar;
a = shape(1:6, 2, 3);
b = shape(7:10, 2, 2);
run colocarTitulo("Matrices");
print a;
run colocarLinea;
print b;
run colocarLinea;
print a b;
run colocarTitulo("Matrices traspuestas");
print (a`);
run colocarLinea;
print (b`);
quit;
/* Ej 5. Procedimiento proced1 */
proc iml;
reset storage = subalg.ejemplos;
a = 5;
b = 2;
run proced1(a, b, c, d);
print a b c d;
quit;
/* Ej 6. Procedimiento proced2 */
proc iml;
reset storage = subalg.ejemplos;
a = 5;
b = 2;
run proced2(a, b);
print a b;
quit;
/* Ej 7. Pasaje por referencia en una función */
proc iml;
reset storage = subalg.ejemplos;
a = 3;
b = 5;
c = fun(a, b - a);
print a b c;
quit;
/* Ej 8. Pasaje por referencia en un procedimiento */
proc iml;
reset storage = subalg.ejemplos;
a = 8;
b = 4;
run miProc(a, b);
print a b ;
quit;
/* Ej 9. Variables globales */
proc iml;
reset storage = subalg.ejemplos;
x = 2;
z = 10;
y = fcn(x);
print x z y;
quit;