Rexx-skolan

Del 1: Gör en miniräknare

Vad är Rexx?

Rexx är ett skript-språk som är integrerat i Warp. Rexx-program är egentligen vanliga textfiler som har ändelsen cmd. Du programmerar i t ex E eller EPM, sparar och Rexx-programmet är klart för att köras.

Uppgiften

Här ska vi göra en väldigt simpel miniräknare. Det ingår ju ingen i Warp så därför kan det vara en lämplig uppgift.

Vi sätter igång!

Öppna din favorit-redigerare. E är en gammal trotjänare. Dags för första raden. Den är faktiskt lite viktig. Den måste börja med /* och sluta med */. Vad som står mellan är mindre viktigt. Denna rad talar om för OS/2 att detta är ett Rexx-program. Om raden inte innehåller dessa /* */ så tror OS/2 att det är en batch-fil. Så första raden blir alltså:

/* Min miniräknare */

Det kan vara trevligt att få reda på miniräknarens namn. För att skriva ut detta använder vi nyckelordet say. Andra raden:

say "Pelles lilla miniräknare v1.0";

Semikolonet på slutet behövs inte, men för god programmeringsvana skriver vi ut det.

Kolla parametrar

Nästa steg blir att hämta in något matte-tal från användaren. Det går naturligtvis att göra detta på många sätt. Här fångar vi upp de parametrar som användaren skickar med vid programstart. För att hämta parametrar använder vi arg(x) där x är vilken parameter vi ska hämta i ordningen, från 1. Men vad händer om användaren inte anger några parametrar? För att undvika fel, måste vi kolla om det verkligen skrevs några parametrar. För detta använder vi en traditionell if-sats. Vi testar om första parametern är en tom sträng med:

if arg(1) == ''

Om detta villkor uppfylls vi vill ju göra något, annars vore det ju ingen vits. Detta leder oss till:

if arg(1) == '' then do

Nyckelorden do berättar att det är flera följande satser som ska exekveras om villkoret uppfylls. Vi måste därmed sluta satsblocket med end. Vad vill vi nu göra om användaren inte angav någon parameter? Jo, först kan vi skriva ut ett litet felmeddelande. Här använder vi say igen:

say "Syntax error.";

Efter det vill vi avbryta programmet och ge användaren en chans till ett nytt försök. Ett Rexx-program avslutas med nyckelordet exit. Man kan skicka med ett returvärde, men i detta fall har vi ingen nytta av det. Raden blir rätt och slätt:

exit;

Vi sammanfattar:

if arg(1) == '' then do
  say "Syntax error.";
  exit;
end

Räkna

Nu kommer vi till det väsentliga, nämnligen räkna ut talet som användaren angav. Men innan det ska vi upprepa talet, dvs vi skriver ut första parametern:

say arg(1);

För att utföra själva räkneprocessen använder vi interpret. Detta nyckelord är mycket kraftfullt. Det gör så att efterföljande textsträng exekveras som om det var skrivit direkt på raden. Det är lite krångligt att förklara hur det fungerar men raden blir i alla fall:

interpret "say "||arg(1);

De lodräta strecken || kopplar ihop två textsträngar till en.

Sammanfattning

Nu är programmet klart och det är (om du inte gjort det tidigare) dags att spara filen med ett passande namn t ex rakna.cmd. Hela koden ser nu ut ungefär så här:

/* Min miniräknare */
 
say "Pelles lilla miniräknare v1.0";
 
if arg(1) == '' then do
  say "Syntax error.";
  exit;
end
 
say arg(1);
interpret "say "||arg(1);

Vi testar programmet genom att öppna en OS/2-prompt och skriva:

rakna 1+1

Resultatet blir ungefär så här:

[D:\]rakna 1+1                  
Pelles lilla miniräknare v1.0   
1+1                             
2                               
 
[D:\]                           

Du måste ange talet utan mellanslag. Om du använder mellanslag så få vi flera parametrar och i detta exempel plockar vi bara upp det första.

Del 2: Förbättra räknaren

I del 1 gjorde vi en helt fungerande miniräknare, men det finns naturligtvis lite att förbättra.

Första raden

Vi börjar med en ny fil och första raden måste som alltid vara en kommentar.

/* Förbättrad miniräknare */

Parameterkoll

Som med förra räknaren, måste vi kolla om användaren skrev någon/några parametrar:

if arg(1) == '' then do
  say "Du måste ange minst en parameter.";
  exit;
end

En stor nackdel med räknaren i del 1 var att programmet bara plockade upp första parametern, dvs, vi var tvingade att skriva räkneuppgiften utan mellanslag. För att slippa detta ska vi slå ihop alla parametrar till en enda sträng. Först, en variabel att samla alla parametrar i:

str = '';

Där skapade vi den tomma variablen str och tilldelade den en tom sträng.

Loop

När vi nu har varibeln str att spara alla variabler i ska vi gå igenom alla parametrar, ett efter ett. En loop skapar man med nyckelordet do. Vi vet inte hur många parametrar användaren gav så vi får ta till ett högt värde som absolut sista parametern, t ex 999. Vi startar loopen:

do i = 1 to 999

Där dök en ny variabel upp, i, som kommmer vara 1 första gången loopen körs, och sedan ökas med ett för varje varv tills i är 999. Nu är det ju onödigt att hoppa runt 999 gånger, eftersom så många parametrar knappast kommer att skrivas in. Därför en liten if-sats som kollar om den finns fler parametrar.

if arg(i) == '' then leave;

Detta kollar om argument nr i finns. Om det inte finns så anropar vi nyckelordet leave. leave gör att Rexx-tolken lämnar loopen och fortsätter körningen där efter.

För varje varv i loopen lägger vi till argument nr i till str:

str = str||arg(i);

Sedan återstår bara att avsluta loopen med...

end

Hela loopen ser då ut så här:

do i = 1 to 999
  if arg(i) == '' then leave;
  str = str||arg(i);
end

Exakthet

I Rexx kan man bestämma exaktheten på räkneoperationer och maxvärdet på tal med nyckelordet numeric. För att vår räknare ska klara av större tal på ett bra sätt använder vi raden:

numeric digits 30

Större värde ger större exakthet men tar mer processorkraft. Standardvärde är 9.

Räkna och utskrift

Allt vi behöver för detta är en rad med interpret, även om en ganska avancerad sådan.

interpret "say '"||str||" = '"||str;

Om vi kör programmet med parametern 2*2 skulle raden exekveras som:

say '2*2 = '2*2

Resultat när vi kör programmet:

[D:\]rakna 2*2  
2*2 = 4         
                
[D:\]           

Integrera med skrivbordet

För att göra räknaren lätt-tillgänglig i alla lägen, varför inte lägga skugga i WarpCenter? För att det hela ska fungera måste du öppna Egenskaper för CMD-filen och i textfältet Parametrar ange:

%* [Räknare - ange räkneuppgift]

Stäng blädderblocket och skapa en skugga i WarpCenter eller på skrivbordet om du inte redan har gjort det. För att vår räknare inte ska visa resultatet för en del av en sekund och sedan låta fönstret försvinna, lägger vi till en rad sist i CMD-filen:

'@pause > nul'

Detta anropar det lilla programmet pause. Snabel-a gör att själva pause-kommandot inte visas och > nul gör att programmets utdata inte heller visas.

Ytterligare förbättringar

Nyckelordet interpret är väldigt kraftfullt, så varför inte utnyttja detta till att hämta upp konstanter eller t.o.m anropa funktioner. Ett exempel: Vi skapar i koden en konstant för pi:

PI = 3.14

Detta är allt som behövs för att sedan använda PI när du anger parametrar. T.ex 2*PI ger utskriften:

2*PI = 6.28

Hela koden

/* Förbättrad miniräknare */
 
if arg(1) == '' then do
  say "Du måste ange minst en parameter.";
  exit;
end
 
str = '';
do i = 1 to 999
  if arg(i) == '' then leave;
  str = str||arg(i);
end
 
numeric digits 30
PI = 3.14
 
interpret "say '"||str||" = '"||str;
 
'@pause > nul'