Seed7

Istruzioni e varie

E' arrivato il momento di esaminare le operazioni e le istruzioni più comuni anche in Seed7. Che, come immaginerete, ricalcano da vicino le istruzioni analoghe di altri linguaggi.

La prima è il solito if, noto operatore di selezione:
Il formato è il seguente:

if espressione booleana then
istruzioni
elsif espressione booleana then
istruzioni
else
istruzioni
end if


L'espressione deve essere di tipo booleano. In caso di più istruzioni nello stesso ramo non è necessario fare nulla, la delimitazione è, come consueto in Seed7, garantita dal formato stesso. la keyword else è da intendersi come clausola "rastrello" che include tutti i casi non compresi nei rami precedenti.  L'esempio chiarisce l'uso pratico.

  Esempio 3.1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ include "seed7_05.s7i";

const proc: main is func
local
var integer: x1 is 0;
begin
write("Inserisci un numero: ");
readln(x1);
if (x1 < 0) then
writeln("Hai inserito un numero < 0");
elsif (x1 = 0) then
writeln("Hai inserito proprio 0");
else
writeln("Hai inserito un numero > 0");
writeln("Buona scelta");
end if
end func;

L'esecuzione di un ramo esclude automaticamente gli altri. Ovviamente elsif ed else sono opzionali.
L'istruzione non prevede altre difficoltà.

Molto vicino a if è, come sempre, case. Si tratta di un altro noto selettore che è più elegante e leggibile rispetto ad una lunga sequenza di if rispetto al quale si pone spesso come alternativa più "elegante". Anche in questo caso ci sono poche difficoltà:

case espressione of
when {valori}:
istruzioni
when {valori}:
istruzioni
........
otherwise:
istruzioni
end case


Il range di valori va sempre messo all'interno delle parentesi graffe. Il ramo determinato da otherise comprende le casistiche non considerate nei rami precedenti ed ovviamente opzionale. Come si può vedere diversamente da altri linguaggi non è necessario mettere la classica clausola break che impedisce il fenomeno del fall-through che in Seed7 è automaticamente evitato.

  Esempio 3.2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$ include "seed7_05.s7i";

const proc: main is func
local
var integer: x1 is 0;
begin
write("Inserisci un numero: ");
readln(x1);
case x1 of
when {0}:
writeln("Hai inserito il numero 0");
when {1 .. 10}:
writeln("Hai inserito un numero tra 1 e 10 compresi");
otherwise:
writeln("Numero > di 10 o negativo");
end case;
end func;

La riga 12 ci presenta la possibilità di inserire un range di valori contiguo. E' peraltro possibile inserire anche un insieme più causale, ad esempio:

when {1,2,8,50}

che è un modo decisamente conciso ed elegante che non si riscontra, stranamente, in altri linguaggi (tipo C#) dove questa possibilità è espressa in maniera molto più, come dire, antiestetica.

Analogamente a quanto visto con "if" il primo ramo eseguito taglia fuori i successivi.

Anche il classico for non presenta soverchie problematiche concettuali. E' il classico iteratore che ripete un dato numero di volte, anche infinito, una certa operazione. Il formato è un po' più "verboso" a prima vista rispetto ad altri linguaggi:

for identificatore range espressione to espressione do
istruzioni
end for


Il "to" può essere sostituito con downto qualora si vada da un valore alto verso un valore più basso. Subito l'esempio:

  Esempio 3.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ include "seed7_05.s7i";

const proc: main is func
local
var integer: x1 is 0;
var integer: x2 is 0;
begin
write("Inserisci un numero: ");
readln(x1);
for x2 range 0 to x1 do
writeln(x2);
writeln(x1 - x2);
end for;
end func;

In questo caso il secondo estremo è costituito da una variabile.
Per quanto riguarda for abbiamo anche un seconda forma che prevede un range vero e proprio invece dell'indicazione di due estremi:

for identificatore range lista do
istruzioni
end for


  Esempio 3.4
1
2
3
4
5
6
7
8
9
10
$ include "seed7_05.s7i";

const proc: main is func
local
var char: x1 is ' ';
begin
for x1 range "abcd" do
writeln(x1);
end for;
end func;

in questo caso effettuando il ciclo su una sequenza di caratteri.
Anche in Seed7 è possibile manovrare sull'incremento della variabile che funziona da indice; per fare questo si usa la keyword step, per esempio è possibile modificare la riga 10 dell'esempio 3.3 come segue:

for x2 range 0 to x1 step 2 do

in questo modo x2 varrà 0,2,4... ecc....

Altro interessante iteratore è il while. La forma con cui si presenta è semplicissima

while espressione booleana do
istruzioni
end while


il ciclo viene eseguito fintanto che l'espressione booleana è true. Se non diventa mai false allora il loop è infinito. Se è false da subito invece le istruzioni all'interno del while non vengono mai eseguite. Il comportamento è assolutamente analogo a quello riscontrato in altri linguaggi.

  Esempio 3.5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ include "seed7_05.s7i";

const proc: main is func
local
var integer: x1 is 0;
var integer: x2 is 0;
begin
write("Inserisci un numero: ");
readln(x1);
while x2 < x1 do
writeln(x2);
writeln(x1 - x2);
x2 := x2 + 1;
end while;
end func;

La riga 13 comporta un necessario incremento della variabile x2 che nell'esempio relativo all'istruzione for, vedasi il 3.3, viene aumentata automaticamente ,qui invece deve essere modificata a mano.

Come ultima istruzione iterativa abbiamo l'accoppiata repeat - until. E' così impostata:

repeat
istruzioni
until espressione booleana


diversamente dal while le istruzioni vengono ripetute finche l'espressione booleana non diventa true (invece che false). Ancor più importante è annotare che le istruzioni stesse vengono comunque eseguite almeno una volta, in quanto il codice viene valutato in sequenza, non c'è un salto per esaminare il valore della espressione.


  Esempio 3.6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ include "seed7_05.s7i";

const proc: main is func
local
var integer: x1 is 0;
var integer: x2 is 10;
begin
write("Inserisci un numero: ");
readln(x1);
repeat
writeln(x2);
writeln(x1);
x1 := x1 + 1;
until (x1 > x2);
end func;

Anche in questo caso attenzione ai loop infiniti....