Volver menú revistas Volver página anterior

El Amiga Me Encanta ha conseguido el permiso por escrito de IDG Comunications España para ofrecer los artículos de la revista Amiga World España.

Nº 44 - Junio 1993
Amiga World

CURSO DE ARexx (6ª PARTE)


Por Jesús Diez

Bienvenidos a nuestra cita habitual con el ARexx. Este capítulo seguirá completando el extenso glosario de instrucciones que iniciacmos hace dos meses, y que concluirá probablemente en el próximo número de la revista, para dar paso a la lista de funciones de la librería interna del lenguaje. Hoy comenzaremos por:


17.- OPTIONS


Esta instrucción sirve para definir algunas opciones internas del ARexx. Admite tres posibles sintaxis, con significados muy diferentes:

OPTIONS FAILAT número
De esta forma podemos indicar al ARexx el valor límite a partir del cual, los valores devueltos por llamadas a funciones o comandos externos, serán considerados como códigos de error y no como resultados válidos.

OPTIONS PROMPT "texto"
Así podemos usar una cadena de texto a nuestra elección, para indicar al usuario del programa cuando debe teclear un dato. A partir de ese momento, y mientras no sea cambiado, servirá como encabezamiento a todos los "PULL" de datos que hagamos en el programa. Prueben por ejemplo: OPTIONS PROMPT "->"


OPTIONS RESULTS
Con esta instrucción se obliga al ARexx a esperar siempre una cadena como resultado de todas las llamadas a comandos de programas externos, emitiendo un error si no hay resultado. Por defecto, el ARexx mantiene esta opción desactivada.

Si en el programa aparece el comando OPTIONS sin ningún texto detrás, podemos devolver todos los cambios realizados a sus valores por defecto.


18.- OTHERWISE

Sirve como complemento de la instrucción SELECT que veremos un poco más adelante, continuando con el orden alfabético. De momento basta decir que OTHERWISE sirve para expresar la acción a realizar cuando ninguna de las condiciones de SELECT se cumple. En la práctica viene a representar algo parecido a lo que hace "ELSE" con la instrucción condicional "IF".


19.- PARSE

Aquí llegamos a otra de esas potentísimas instrucciones que hacen del ARexx un lenguaje tan especial. "PARSE" nos proporciona una forma de extraer de forma precisa subcadenas de información desde un texto mayor y asignarlo a variables. Una de sus aplicaciones más útiles es la de procesar la entrada de información desde el teclado a un programa. Mediante "PARSE", no tenemos porque limitarnos a recoger un dato de cada vez, como con "PULL", sino que podemos recibir del usuario datos con estructura más compleja, y desglosarlos en sus partes.

El formato general de la instrucción es como sigue:

PARSE fuente variable1 variable2 variable 3 ... ...

Dónde pone "fuente" hay que colocar uno de los indicadores que señalan al ARexx de dónde debe tomar la cadena de datos que se procesará con PARSE. Después aparece una lista de nombres de variables donde se guardará cada dato desglosado de la cadena principal.

Como posibles "fuentes" podemos tener:

a.- EXTERNAL o PULL

Así le decimos que queremos que la cadena sea recogida a través del teclado desde el usuario. A efectos prácticos es como un "PULL", pero recogiendo más de un dato de una vez. Cada palabra o número separado por uno o mas espacioes en la línea, irá a parar a una de las variables especificadas en la lista. Por ejemplo:

SAY "Teclée su nombre, primer apellido y edad, separados por un espacio:" PARSE PULL a b c

Después de este fragmento de programa, y si el usuario ha introducido correctamente los datos solicitados, tendremos el nombre guardado en la variable "a", el primer apellido en la variable "b", y por último la edad, en la variable "c". Otra diferencia con "PULL" a secas, es que aquí no se fuerza la transformación del texto a mayúsculas, conservándose el texto tal y como se tecleó. Si se desea esa transformación se puede hacer con el modificador "UPPER" que se comenta un poco más adelante

b.- ARG

Esta es otra posible fuente de datos para el PARSE. Con ARG podemos rescatar en variables los datos tecleados en la misma línea de arranque del programa ARexx. Por ejemplo, podemos psar uno o mas datos al programa, en la misma línea de texto donde lo arrancamos. Por ejemplo, si invocamos a un supuesto programa ARexx con la línea:

rx programa.rexx Manuel Pérez 27

podremos recoger los datos tecleados después del nombre del programa, si colocamos la siguiente linea al comienzo:

PARSE ARG a b c

Esto tendrá el mismo efecto que el caso anterior, desglosando cada dato separado con uno o más espacios (nombre, apellido y edad), en cada variable especificada.

c.- NUMERIC

Con esta opción podemos recabar los valores activos de cada una de las opciones de NUMERIC (ya vista en el capítulo anterior), en un momento dado durante la ejecución del programa, PARSE las devolverá en este orden: primero DIGITS, luego FUZZ y por último FORM. Así, si escribimos:

PARSE NUMERIC a b c
SAY "DIGITS:" a
SAY "FUZZ:" b
SAY "FORM:" c

Al ejecutar estas instrucciones veremos los valores por defecto que mantiene ARexx para estas tres opciones, siempre y cuando no hayan sido ya previamente modificadas por nosotros mediante una orden "NUMERIC", claro:

DIGITS: 9
FUZZ: 0
FORM: SCIENTIFIC

d.- VAR variable

Con VAR podemos dar entrada a PARSE con el valor que contenga cualquier variable en uso dentro del programa. Así desglosamos el contenido de la varibale especificada en subcadenas que se reparten a su vez en otras variables. La variable original no se ve modificada con el PARSE. Pôr ejemplo:

PARSE VAR dato a b c

Conseguirá desglosar el texto contenido en la variable "dato", en función de los espacios que tenga, en tres subcadenas que irán a su vez a las variables "a", "b" y "c" respectivamente.

e.- WITH

En este caso la fuente de datos será una expresión calculada en la misma linea de invocación del PARSE. Puede ser una llamada a una función externa o interna, o el resultado de una operación con variables de texto. WITH se usa para separar claramente la expresión a calcular, de la lista de variables que contendrá los resultados, así:

PARSE expresión WITH variable1 variable2 ... ...





Si en el programa
aparece el comando
OPTIONS sin ningún
texto detrás,
podemos devolver
todos los cambios
realizados
a sus valores
por defecto

f.- VERSION

Esta es una forma cómoda de averiguar información técnica de la máquina en la que se está corriendo un determinado programa ARexx. Devuelve una cadena cinco datos separados por espacios: versión de ARexx, procesador, coprocesador, formato de vídeo y, por último, frecuencia de vídeo. Por ejemplo en mi modesto Amiga 500, al ejecutar las instrucciones:

PARSE VERSION dato
SAY dato

Obtengo la salida:

ARexx v1.15 68000 NONE PAL 50HZ

Estoy seguro que algunos de los lectores podrán obtener especificaciones más espectaculares. Por cierto, si su apreaciado 3000 les dice que tiene un procesador 68020, no se alarmen. No se trata de que Commodore les haya vendido un modelo "light" de su ordenador para ahorrar costes, sino que algunas versiones de ARexx solo reconocen los procesadores hasta el 68020, ignorando el 030 y, por supuesto, el 040.


g.- SOURCE

Esta es otra opción para recabar información técnica sobre el entorno ARexx sobre el que está corriendo un determinado programa. Evidentemente, toda esta información obtenida mediante PARSE, no solo sirve a título meramente informativo, sino que puede servir para que el programa tome decisiones importantes durante su ejecución. Por ejemplo, podemos averiguar desde el programa, si el ordenador sobre el que está corriendo, posee comprocesador matemático, y en función de lo obtenido, podemos usar una librería de funciones matemáticas que lo aproveche o no.

En este caso, SOURCE nos da una cadena con 6 datos separados por espacios. El primero indica si el programa fue llamado como comando o como función. El segundo es 0 ó 1 en función de si está activada la opción OPTIONS RESULTS. El tercero es el nombre usado para llamar al programa, incluido el path si se ha usado. El cuarto es el nombre del programa sin el path. El quinto es la extensión usada para identificar los programas en ARexx (por defecto ".rexx"). Por último, el sexto contiene el puerto activo para comunicación con programas externos (el activado mediante ADDRESS).

h.- UPPER

Esta última opción no es exactamente un especificador de la fuente de los datos, como los anteriores. Más bien se trata de un modificador que puede aplicarse a cualquiera de los mencionados hasta ahora, para forzar que todo el texto se transforme en mayúsculas al ser procesado y separado en las variables. Por ejemplo:

PARSE UPPER PULL datos variable1 variable2 ... ...

Por último, para terminar con PARSE hay que añadir que hasta ahora he asumido que el criterio que se sigue para separar la cadena de datos original en trozos más pequeños, y asignarlos a la lista de variables, es usando los espacios en blanco. Es decir, cada trozo separado por uno o más espacios en blanco, iría a parar a cada una de las variables de la lista. Esto es cierto, pero PARSE permite aún mayor control de cómo se produce esta asignación. Hay dos formas de hacer este "troceamiento":

a.- Asignación por Tokenización.

Este es el método habitual mencionado de los espacios en blanco, pero hay que completarlo con dos puntualizaciones: Cuando la lista de variables es mayor que el número de fragmentos separados por espacios en la cadena original, las variables que "sobren" serán asignadas a un carácter nulo (NULL). Por el contrario, si el número de variables es menor, la asignación se hará normalmente, pero la última variable recibirá todo el resto del texto como un espacio delante. Por ejemplo:

texto="Revista Amiga World"
PARSE texto var1 var2

En este caso, la asignación efectuada será:

var1="Revista"
var2=" Amiga World"

si queremos hacer un salto en uno de los fragmentos de la asignación de variables se usa el carácter punto (.). Siguiendo con nuestro ejemplo:

texto="Revista Amiga World"
PARSE texto var1. var2

En este caso, la asignación efectuada será:

var1="Revista"
var2=" World"

El espacio situado delante del texto de la última asignación se evita colocando un punto como último elemento de la lista de variables:

PARSE VAR texto var1. var2.

b.- Asignación por Posición.

En este otro tipo, nosotros podemos indicar las posiciones absolutas o relativas en que queramos partir la cadena primitiva, para asignar cada fragmento a cada una de las variables. Se pueden usar posiciones absolutas aportando sumplemente el número de carácter dentro de la cadena, o relativas a la última especificada, dando la posición como +n ó -n. Por ejemplo:


texto="abcdefghijklmno"
PARSE VAR texto 1 a 3 b +4 c -3 d

Así tendremos:

var1="ab" (desde la 1 hasta la 2)
var2="cdef" (desde la tres hasta cuatro por delante)
var3="ghijklmno" (desde la última posición especificada, hasta el final)
var4="defghijklmno" (desde 3 posiciones menos que la última especificada, hasta el final=.

Una vez más les recomiendo que experimenten con diferentes posibilidades, y observen que resultados producen. Es, sin duda, la mejor forma de familiarizarse con la instrucción PARSE.




Algunas versiones
de ARexx sólo
reconocen
hasta el 68020,
ignorando
el 030 y,
por supuesto,
el 040

 

20.- PROCEDURE

En uno de los capítulos iniciales, ya comenté los sencillo que es definir funciones dentro de un programa ARexx. Pero si alguno de ustedes, con experiencia en otros lenguajes de programación, ha estado experimentando, se habrá dado cuenta de un hecho significativo: Si nos ceñimos a lo explicado entonces, todas las variables que se usan dentro de las funciones son comunes al resto del programa. Es decir, la variable que se inicialice en el cuerpo del programa, puede ser leída y modificada desde cualquier función, y viceversa. Estas variables se suelen denominar "globales" y pueden ser útiles en muchas ocasiones, pero no permiten una verdadera programación estructurada, en la que un programa complejo se pueda construir a base de subfunciones realizadas de forma independiente, incluso por personas diferentes, sin que ello signifique ningún problema. Para que esta forma de programar sea viable, es necesaria la existencia de las denominadas "variables locales". Estas variables son propias de cada función y no entran en conflicto con cualquier otra variable con el mismo nombre que pueda existir en el cuerpo principal del programa o en otra función. Usándolas, podemos aislar los problemas de programación en tareas más sencillas, que permiten un enfoque más eficaz, sin preocuparnos más que de pasar los datos necesarios a las funciones y recoger el resultado que devuelvan, sin preocuparnos de como trabaja internamente esa función. Los programas así construidos son más fáciles de depurar y corregir, y lo que es más importante, representan una verdadera inversión de futuro para el programador, ya que permiten reutilizar el código en otros nuevos programas. Muchos programadores experimentados, mantienen sus propias librerías de funciones utiles, de forma que cuando se enfrentan a un nuevo programa, tienen el 80% del trabajo hecho.

Después de esta apología de la programación estructurada, nadie dudará de que el ARexx también puede solventar el problema de las variables locales, y estar a la altura de los mejores lenguajes estructurados. Aquí es donde entra en juego la instrucción "PROCEDURE".

Cuando se incluye PROCEDURE como primera instrucción de la función, todas las variables que se definen dentro de ella pasarán a ser locales, sin mas problemas. Por ejemplo:

/* Variables locales */
n=1
say "La variable n en el programa es:" n
call funcion()
say "La variable n en el programa todavía es:" n
exit
funcion:
PROCEDURE
n=2
say "La variable n en la función es:" n
return

Como pueden ver en este pequeño ejemplo, la variable "n" existe por duplicado en el programa y en la función. Al comenzar el programa, se le da el valor 1, pero luego se llama a la función donde a "n" se le asigna el valor 2. Al volver al programa principal meidante "return", se vuelve a imprimir el valor de "n" para comprobar que efectivamente se conserva el valor inicial, y que la "n" de la función no tiene nada que ver con la "n" del bloque principal. Ahora les invito a que prueben el mismo programa, pero omitiendo la linea PROCEDURE, y comprueben el resultado.

Para terminar, hay que apuntar que en determinados casos puede ser recomendable el uso de alguna variable "global" conviviendo con las "locales", de forma que su valor sea común a todo el programa y sus funciones, y evitar pasar su valor como argumento de las funciones. Esto se hace añadiendo el modificador EXPOSE, de la siguiente manera:

PROCEDURE EXPOSE var1 var2

Así, todas las variables de la función serán locales, excepto var1 y var2 que serán globales.

Y por hoy, nada más. Hasta el mes que viene, reciban un codial saludo.


Volver menú revistas Volver página anterior