ZIG - Selezione con if
Nessun linguaggio di programmazione che si rispetti può fare a meno di istruzioni che permettono di effettuare delle valutazioni di carattere selettivo o comparativo. In questo ambito troveremo alcuni dei concetti già visti, come le oprazioni di confronto con uso dei relativi operatori.
La prima istruzione che affrontiamo è quella di selezione. Le parole chiave sono if e else come in altri linguaggi. Il costrutto che stiamo per incontrare ha 3 forme:
-
if (condizione booleana) {
istruzioni
}
nel caso in cui le istruzioni si riducessero ad una sola le parentesi graffe possono essere tralasciate. Le parentesi tonde che circondano la condizione booleana sono invece obbligatorie. -
if (condizione booleana) {
istruzioni
}
else {
istruzioni
}
valgono le considerazioni precedenti. -
if (condizione booleana) {
istruzioni
}
else if (condizione booleana) {
istruzioni
}
else if.....
else {
istruzioni
}
in questo caso le ramificazioni introdotte da else if possono essere numerose quanto ci pare, anche se in caso di numero troppo elevato si può ricorrere ad altro costrutto, come vedremo, per migliorare la leggibilità, o rivedere l'impostazione del problema. Gli esempi seguenti sono molto semplici, direi decisamente basilari, d'altronde vedrete nel capitolo dedicato che inserire l'input da utente appesantirebbe di molto il codice. Avrete anche notato che entrano pesantemente in gioco le espressioni booleane.
1)
const std = @import("std");
pub fn main() !void {
const x1 = 7;
if (x1 == 7)
std.debug.print("x1 vale 7\n", .{});
}
2)const std = @import("std");
pub fn main() !void {
const x1 = 6;
if (x1 == 7)
std.debug.print("x1 vale 7\n", .{})
else std.debug.print("x1 non vale 7\n", .{});
}
3)const std = @import("std");
pub fn main() !void {
const
x1 = 6;
if (x1 == 7) std.debug.print("x1 vale 7\n", .{})
else if (x1 == 3) std.debug.print("x1 non vale 3\n", .{})
else
std.debug.print("x1 non vale ne 7 ne 3\n", .{});
}
In questo caso abbiamo usato istruzioni singole e si noti che non ci sono punti e virgola per separare i vari branch. A questo punto per completezza vediamo un esempio con più istruzioni in ogni ramo della selezione. Concettualmente non cambia nulla:
const std = @import("std");
pub fn main() !void {
const x1 =
6;
if (x1 == 7) {
std.debug.print("x1 vale
7\n", .{});
std.debug.print("quindi dispari!\n");
}
else if (x1 == 3) {
std.debug.print("x1
vale 3\n", .{});
std.debug.print("quindi
dispari!\n");
}
else {
std.debug.print("x1 non vale ne 7 ne 3\n", .{});
std.debug.print("quindi vale 6\n", .{});
}
}
Le raccomandazioni sono le solite che si danno in tutti i linguaggi, come detto non esagerare con i rami da valutare, attenzione alle espressioni booleane e ai valori che si inseriscono. Non è previsto il fall-through per cui il primo ramo che viene eseguito esclude la possibilità di entrare negli altri. Questa è cosa molto buona.
In molti altri linguaggi abbiamo il cosiddetto operatore ternario, ad esempio in C:
int a = 10, b = 20, c;
c = (a < b) ? a : b;
la seconda riga evidenzia l'istruzione che sostituisce la seguente
sequenza, che ha lo
stesso effetto ma risulta più verbosa:
if a < b {
c = a;
}
else {
c = b;
}
Ebbene Zig vuole che tutto sia chiaro (negli intenti....) e quindi non usa : ? e simboli vari ma cerca di essere più esplicito possibile:
Esempio 7.1
const std = @import("std");
pub fn main() void {
const x1: u32 = 10;
const x2: u32 = 5;
const x3: = if (x1 != x2) (x1 + x2) else (x1 * x2);
std.debug.print("Risultato: {}\n", .{x3});
}
La ldefinizione di x3 evidenzia il procedimento. In questo
caso la nostra selezione viene adoperata come espressione il cui risultato
viene riversato in una costante. Niente simboli quindi, parole
chiare ed evidenti.
A proposito di parole chiare ed evidenti eccoci ad
esaminare un semplice esempio in cui la condizione è composta da più
ipotesi:
Esempio 7.2
const std = @import("std");
pub fn main() void {
const x1: u32 = 10;
if ((x1 > 9) and (x1 < 11)) {
std.debug.print("x1 vale proprio 10\n", .{});
}
}
Come avrete notato "and" è stato scritto esplicitamente, ne avevamo
parlato nel capitolo dei booleani. L'uso di una parentesi "globale"
che contenga tutti i confronti è necessario.
Abbiamo evidenziato
come non sia buona pratica accumulare troppe sequenze composte da else if.
Esiste un altro costrutto per gestire queste situazioni che vedremo nel
prossimo paragrafo.