Usa Rexx per lo scripting nel 2023
Ecco due semplici programmi per mostrare quanto sia facile leggere, scrivere e mantenere Rexx.
In un articolo precedente, ho mostrato come il linguaggio di scripting Rexx sia potente e facile da usare. Utilizza tecniche specifiche per conciliare questi due obiettivi che sono spesso considerati in conflitto.
Questo articolo ti guida attraverso due esempi di script Rexx in modo che tu possa avere un'idea del linguaggio. Rexx pretende di essere altamente capace ma facile da lavorare.
Un esempio di uno script Rexx
Il linguaggio di programmazione LISP è famoso per l'uso eccessivo di parentesi. Può essere una vera sfida per i programmatori garantire che siano tutti abbinati correttamente.
Questo breve script legge una riga di codice LISP dall'utente e determina se le parentesi nell'input corrispondono correttamente. Se le parentesi non sono bilanciate correttamente, il programma visualizza un errore di sintassi.
Di seguito sono riportati tre esempi di interazioni con il programma. Nel primo, il codice LISP che ho inserito era digitato correttamente. Ma i due successivi contengono parentesi non corrispondenti identificate dallo script Rexx:
Enter a line to analyze:
(SECOND (LAMBDA (LIS) (FIRST (CDR LIS)) ))
Parentheses are balanced
Enter a line to analyze:
((EQSTR (CAR LIS1) (CAR LIS2))
Syntax error: too many left parens, not balanced
Enter a line to analyze:
(EQSTR (CAR LIS1) CAR LIS2))
Syntax error: right paren before or without left paren
Ecco il programma Rexx:
counter = 0 /* counts parentheses */
say 'Enter a line to analyze:' /* prompts user for input */
pull input_string /* reads line of user input */
length_of_string = length(input_string)
/* process each character of the input line, one at a time */
do j = 1 to length_of_string while counter >= 0
character = substr(input_string,j,1)
if character = '(' then counter = counter + 1
if character = ')' then counter = counter - 1
end
/* display the appropriate message to the user */
if counter = 0 then
say 'Parentheses are balanced'
else if counter < 0 then
say 'Syntax error: right paren before or without left paren'
else
say 'Syntax error: too many left parens, not balanced'
Innanzitutto, il programma richiede all'utente di inserire una riga di input con l'istruzione say
. Quindi lo legge con un'istruzione pull
.
Le istruzioni say
e pull
vengono utilizzate per input e output conversazionali o per l'interazione diretta con gli utenti. Rexx supporta anche I/O orientato ai caratteri e orientato alla linea o ai record.
Successivamente, lo script utilizza la funzione length
per inserire la lunghezza della riga di input nella variabile length_of_string
.
Il ciclo do
elabora ogni carattere dalla riga di input, uno alla volta. Incrementa il contatore
ogni volta che incontra una parentesi sinistra e lo decrementa ogni volta che riconosce una parentesi destra.
Se il contatore
finisce come zero dopo aver elaborato l'intera riga di input, il programma sa che tutte le parentesi nella riga di input corrispondono correttamente. Se il contatore
non è 0 dopo l'elaborazione, la riga di input presenta parentesi non corrispondenti.
Le istruzioni if
finali mostrano il messaggio corretto all'utente. È possibile codificare queste istruzioni if
in un numero qualsiasi di stili, a seconda delle preferenze individuali. (Il requisito principale è che ogni volta che più istruzioni vengono codificate all'interno di un ramo, devono essere racchiuse in un gruppo do...end
.)
Questo programma mostra che Rexx è in formato libero e non fa distinzione tra maiuscole e minuscole. Non si basa su parole riservate, quindi sei libero di utilizzare parole comuni come counter
o character
per rappresentare le variabili.
L'unico requisito fondamentale che Rexx impone è che qualsiasi funzione deve essere immediatamente seguita da una parentesi aperta. Esempi nel programma sono le funzioni length
e substr
. Metti uno spazio tra il nome di una funzione e la sua parentesi successiva e Rexx non riconoscerà la funzione.
A parte alcuni requisiti minimi come questi, Rexx richiede molto poco al programmatore in termini di sintassi, caratteri speciali o regole di codifica restrittive.
I programmi Rexx appaiono e si leggono come pseudo-codice. Ciò li rende relativamente facili da leggere e da utilizzare.
Un esempio reale di uno script Rexx
Ecco un programma dal mondo reale:
Les Koehler, un utente Rexx, disponeva di un programma di contabilità legacy che confrontava i record contabili a disposizione con quelli che un fornitore gli inviava quotidianamente. Il programma legacy è stato eseguito per diverse ore ogni giorno per elaborare 25.000 record. Utilizzava una tecnica sequenziale di "percorri l'elenco" per confrontare un set di record con l'altro.
Les ha sostituito il programma legacy con uno script Rexx. Lo script Rexx esegue la corrispondenza utilizzando array associativi:
/* Create an associative array reflecting */
/* the values in the first list of names */
/* by Les Koehler */
flag. = 0 /* Create array, set all items to 0 */
do a = 1 to list_a.0 /* Process all existing records */
aa = strip(list_a.a) /* Strip preceding/trailing blanks */
flag.aa = 1 /* Mark each record with a 1 */
end
/* Try to match names in the second list */
/* against those in the associative array */
m = 0 /* M counts number of missing names */
do b = 1 to list_b.0 /* Look for matching name from LIST_B */
bb = strip(list_b.b) /* Put LIST_B name into variable BB */
if \ flag.bb then do /* If name isn't in FLAG array */
m = m+1 /* add 1 to count of missing names */
missing.m = bb /* add missing name to MISSING array */
end
end
missing.0 = m /* Save the count of unmatched names */
Les è riuscito a ridurre i tempi di elaborazione da diverse ore a pochi secondi.
La prima riga di codice (flag.=0
) crea un nuovo array chiamato flag
e inizializza ogni elemento in quell'array su 0
.
L'array list_a
contiene tutti i record contabili esistenti. Il suo primo elemento (list_a.0
) per convenzione contiene il numero di elementi dell'array.
Quindi il primo ciclo do
elabora tutti gli elementi nell'array di record esistenti (list_a
) e contrassegna ciascuno di essi come esistente nell'array flag
. L'istruzione flag.aa=1
contrassegna l'elemento indirizzabile dal contenuto nell'array flag
come presente.
Il secondo ciclo do
distribuisce ogni elemento nell'insieme di nuovi record, contenuti nell'array chiamato list_b
.
L'istruzione if
controlla se un elemento del secondo array di record è contrassegnato come presente nell'array flag
. In caso contrario il programma incrementa il numero di voci presenti nella nuova lista di registrazioni contabili che non esistono nella vecchia lista di registrazioni. E inserisce l'elemento mancante nell'array missing
: missing.m=bb
.
L'istruzione finale (missing.0=m
) aggiorna semplicemente il numero di elementi nell'array missing
, per convenzione memorizzato nella posizione 0 dell'array.
Miglioramenti del Rexx
Perché questo programma Rexx è così veloce rispetto al codice legacy che sostituisce? Innanzitutto, gli array associativi consentono la ricerca diretta di un nuovo record rispetto ai vecchi record. L'accesso diretto è molto più veloce della tecnica sequenziale "walk-the-list" che ha sostituito.
In secondo luogo, tutti gli elementi dell'array risiedono in memoria. Una volta inizializzati i file dei vecchi e dei nuovi record contabili negli array Rexx, non sono necessarie ulteriori operazioni di I/O su disco. L'I/O del disco è sempre molto più lento dell'accesso alla memoria.
Un array Rexx si espande tanto quanto la memoria lo consente. Questo script sfrutta i computer moderni con quantità apparentemente infinite di RAM e libera il programmatore dalla gestione della memoria.
Conclusione
Spero che questi due semplici programmi abbiano dimostrato quanto sia facile leggere, scrivere e mantenere Rexx. Rexx è progettato per scaricare l'onere della programmazione sulla macchina invece che sul programmatore. Eppure il linguaggio ha ancora molto potere, grazie alle tecniche di progettazione che ho descritto in questa serie di articoli.
Per download, strumenti, tutorial e altro ancora gratuiti di Rexx, visita RexxInfo.org. Puoi iscriverti gratuitamente alla Rexx Language Association.
Questo articolo è dedicato alla memoria di Les Koehler, che fu attivo con Rexx e la comunità Rexx fin dai loro primi giorni.