domingo, 9 de septiembre de 2007

Macros REXX en IBM Works

Mientras intento recuperarme de la impresión de ver 300, la adaptación del cómic de Frank Miller al cine (Miller, aunque algunos no le perdonemos aun el guion de Robocop 2, parece tener bastante más suerte en esto que el pobre de Alan Moore), me gustaría hablar de cómo estaban implementadas las macros en una aplicación que ya tiene más de 10 años: IBM Works.

Las macros, desde el punto de vista de un usuario final, son conjuntos de acciones que permiten ahorrar trabajo al usuario en un programa concreto. Ejecutando la macro al pulsar una combinación de teclas, pulsar un elemento de un menú, seleccionarla en un diálogo o como permita el programa, el usuario puede evitar realizar tareas repetitivas como inserta el carácter hebreo aleph, selecciona el párrafo y dale otro formato...

Ocasionalmente, las macros pueden tener una lógica interna más allá de una secuencia de tareas repetitivas y entonces el modo de realizarlas es a través de un lenguaje de programación de macros. Y son de estas macros de las que quiero hablar.

El problema que siempre ha existido con los lenguajes de programación de macros es que son específicos de la aplicación: el cliente IRC mIRC tiene su lenguaje de macros, Microsoft Office hasta ahora ha utilizado una variante de BASIC (Visual Basic for Applications), Open Office ha utilizado otra variante de BASIC, Lotus SmartSuite utiliza LotusScript, el editor de audio Audacity usa su propio lenguaje...

Esto quiere decir que si el usuario desea aprender un lenguaje de macros, probablemente no pueda reutilizar sus conocimientos en otro sitio. Además, en algunos casos, la complejidad del lenguaje de macros para el tipo de tarea que desea el usuario puede resultarle excesiva (se encuentra con tipos de variables, declaraciones, módulos, objetos, métodos, sistemas de componentes y similares incluso para las macros más sencillas).

Cuando hace más de 25 años, Mike Cowlishaw creó el lenguaje de programación REXX, uno de sus propósitos era que fácilmente pudiera ser utilizado como un lenguaje de macros. Y cuando IBM empezó a introducirlo como lenguaje de scripts de todos sus sistemas operativos, también empezó a convertirse en el lenguaje de macros de muchas aplicaciones para esos sistemas.

En el mundo de la informática personal, dos sistemas operativos (uno ajeno a IBM) escogieron implementaciones de REXX como su lenguaje de macros preferido: OS/2 y Amiga OS.

En OS/2 existía un pequeño paquete de oficina llamado IBM Works cuya hoja de cálculo utiliza macros REXX aunque apenas aproveche las posibilidades de esto.




Como puede verse en la segunda imagen, la primera columna corresponde a nombres de personas, la segunda a un NIF (Número de Identificación Fiscal) y la tercera muestra una comprobación de la validez del NIF utilizando una función de la hoja de cálculo IBM Works: =rexx("isValidNIF.fnc",1,1,B4). La función rexx de IBM Works busca un fichero indicado en el primer parámetro (isValidNIF.fnc), decide que el valor de la celda será texto (si tuviésemos 0 en lugar de 1 tras la primera coma, trataría la celda como número) y lo ejecuta pasándole el número de parámetros indicado en el tercero de sus parámetros (en este caso uno)... Y el código de la macro no puede ser más sencillo:
/* isValidNIF.fnc */
parse arg nif
letras = 'TRWAGMYFPDXBNJZSQVHLCKE'
numeros = '0123456789'

letra = right(nif, 1)
dni = left(nif, length(nif) - 1)

select
when pos(letra, letras) = 0 then
ret = 'ERROR: Último carácter no es una letra'
when verify(dni,'1234567890') <> 0 then
ret = 'ERROR: El NIF debe comenzar por un número válido'
when letra = substr(letras, dni//23 + 1, 1) then
ret = 'NIF válido'
otherwise
ret = 'ERROR: La letra no corresponde al DNI'
end

return ret

En esta aplicación concreta, la utilización de REXX como lenguaje de macros se ve reducida a su mínima expresión (al contrario que en casos como gnuplot, gdb, Photo>Graphics, GoServe, EPM...) y a pesar de ello se aprecia la sencillez.

Esto no solventa uno de los problemas de los sistemas de lenguajes de macros: la dependencia de un lenguaje concreto.
Microsoft intentó eliminar la dependencia del lenguaje a través de su sistema de componentes COM que permite utilizar cualquier lenguaje para el que exista un WSE (Windows Scripting Engine) en cualquier aplicación que funcione como WSH (Windows Scripting Host) como son Internet Explorer o IIS, por ejemplo (y no es Microsoft Office, curiosamente), pero el sistema es incómodo para un no iniciado. OpenOffice desde sus últimas versiones permite ejecutar macros en más de un lenguaje, pero el sistema es tan barroco como el caso de los sistemas de Microsoft.
Quizás la aproximación que dando independencia de lenguaje conserva la sencillez es una de las que siguen virtualmente todos los servidores web y algunos editores de texto: la macro se ejecuta por el intérprete deseado y coge la információn necesaria de la entrada estándar, los parámetros y las variables de entorno y devuelve la información a la aplicación a través de su salida estándar. Así es como funcionan los CGIs en los servidores web y las macros en el editor de texto para programadores TextMate (aunque en este caso, la documentación del editor restringe el concepto de macro), por ejemplo.

Es una pena que a veces las cosas sean innecesariamente complejas.

Incidentalmente: en la distribución del intérprete newLISP para Windows puede encontrarse un ejemplo de fichero de Excel que incluye una macro en Visual Basic que define una función que permite ejecutar código newLISP en cualquier fórmula de Excel de un modo muy similar al ejemplo de IBM Works. Y el mismo sistema puede utilizarse para ejecutar código de otros lenguajes.

1 comentario:

DonWarper dijo...

Al guión de Robocop 2 no le pasa nada; al fin y al cabo ¡¡sale el violinista de goma!!

Y tampoco es que Miller tenga más suerte que otros cuando adaptan sus cosas: lo que suele tener es una escopeta recortada en la nuca del director de turno. Pero claro, como el sr. Miller también es humano, se ve que daba sus cabezadas y así debe ser como el otro ha colao en la peli todo lo que chirría: esos añadidos estúpidos que no estaban en el cómic, de los que sin duda la palma se la lleva el hombre cangrejo (y no, no me refiero al de "Me llamo Earl")...

Saludos.