Booleani in Rust
Il tipo booleano in Rust, bool, è uno dei tipi scalari fondamentali del linguaggio. Rappresenta un valore di verità che può essere solo true (vero) o false (falso). In questa guida esploreremo le caratteristiche, le operazioni e gli usi del tipo booleano in Rust.
Il Tipo bool
Il tipo bool in Rust ha esattamente due valori possibili: true e false. Occupa 1 byte (8 bit) in memoria, anche se tecnicamente basterebbe un singolo bit:
fn main() {
let vero: bool = true;
let falso: bool = false;
println!("vero = {}", vero);
println!("falso = {}", falso);
println!("Dimensione di bool: {} byte", std::mem::size_of::<bool>());
// Output: Dimensione di bool: 1 byte
}
L’inferenza dei tipi riconosce automaticamente i letterali booleani:
fn main() {
let a = true; // Tipo inferito: bool
let b = false; // Tipo inferito: bool
println!("a: {}, b: {}", a, b);
}
Operazioni Booleane
I booleani supportano le operazioni logiche fondamentali: AND, OR e NOT.
AND Logico (&&)
Restituisce true solo se entrambi gli operandi sono true:
fn main() {
println!("true && true = {}", true && true); // true
println!("true && false = {}", true && false); // false
println!("false && true = {}", false && true); // false
println!("false && false = {}", false && false); // false
}
OR Logico (||)
Restituisce true se almeno uno degli operandi è true:
fn main() {
println!("true || true = {}", true || true); // true
println!("true || false = {}", true || false); // true
println!("false || true = {}", false || true); // true
println!("false || false = {}", false || false); // false
}
NOT Logico (!)
Inverte il valore booleano:
fn main() {
println!("!true = {}", !true); // false
println!("!false = {}", !false); // true
let attivo = true;
let inattivo = !attivo;
println!("Attivo: {}, Inattivo: {}", attivo, inattivo);
}
Utilizzo nelle Condizioni
I booleani sono il tipo richiesto per le condizioni di if, while e altre strutture di controllo. A differenza di linguaggi come C o JavaScript, Rust non converte automaticamente altri tipi in bool:
fn main() {
let temperatura = 38.5;
let ha_febbre = temperatura > 37.0;
if ha_febbre {
println!("Attenzione: febbre rilevata! ({:.1}°C)", temperatura);
} else {
println!("Temperatura nella norma ({:.1}°C)", temperatura);
}
// In Rust NON è possibile fare:
// if 1 { ... } // Errore! 1 non è bool
// if "ciao" { ... } // Errore! &str non è bool
}
I booleani come espressioni sono utili nelle assegnazioni condizionali:
fn main() {
let eta = 20;
let maggiorenne = eta >= 18;
let messaggio = if maggiorenne { "adulto" } else { "minore" };
println!("Stato: {}", messaggio);
}
Booleani come Risultato di Confronti
Le espressioni di confronto restituiscono sempre un bool:
fn main() {
let a = 10;
let b = 20;
let uguale = a == b; // false
let diverso = a != b; // true
let minore = a < b; // true
let maggiore = a > b; // false
let min_uguale = a <= b; // true
let mag_uguale = a >= b; // false
println!("a == b: {}", uguale);
println!("a != b: {}", diverso);
println!("a < b: {}", minore);
println!("a > b: {}", maggiore);
println!("a <= b: {}", min_uguale);
println!("a >= b: {}", mag_uguale);
}
Combinare Condizioni Booleane
Le operazioni booleane possono essere combinate per creare condizioni complesse:
fn main() {
let eta = 25;
let ha_patente = true;
let ha_esperienza = false;
let puo_guidare = eta >= 18 && ha_patente;
let idoneo_lavoro = ha_patente && (ha_esperienza || eta < 30);
println!("Può guidare: {}", puo_guidare); // true
println!("Idoneo al lavoro: {}", idoneo_lavoro); // true
// Short-circuit evaluation
let risultato = false && {
println!("Questo non viene eseguito!");
true
};
println!("Risultato: {}", risultato); // false
}
Conversione da e verso bool
Da bool a intero
fn main() {
let vero = true;
let falso = false;
// bool -> intero con as
let v_int: i32 = vero as i32; // 1
let f_int: i32 = falso as i32; // 0
println!("true as i32 = {}", v_int);
println!("false as i32 = {}", f_int);
// Utile per conteggi
let valori = vec![true, false, true, true, false];
let conteggio: i32 = valori.iter().map(|&b| b as i32).sum();
println!("Numero di true: {}", conteggio); // 3
}
Da altri tipi a bool
Rust non permette conversioni implicite verso bool. Bisogna essere espliciti:
fn main() {
// Da intero a bool: non esiste una conversione diretta con as
// let b: bool = 1 as bool; // Errore!
// Si usa un confronto esplicito
let numero = 42;
let non_zero = numero != 0;
println!("42 != 0: {}", non_zero); // true
// Da stringa a bool
let s = "true";
let b: bool = s.parse().unwrap();
println!("\"true\".parse() = {}", b); // true
let s2 = "false";
let b2: bool = s2.parse().unwrap();
println!("\"false\".parse() = {}", b2); // false
}
Booleani nei Pattern Matching
I booleani possono essere usati nel pattern matching con match:
fn descrivi_stato(attivo: bool) -> &'static str {
match attivo {
true => "Il sistema è attivo",
false => "Il sistema è spento",
}
}
fn main() {
println!("{}", descrivi_stato(true));
println!("{}", descrivi_stato(false));
}
Conclusione
Il tipo bool in Rust è semplice ma fondamentale. La scelta di Rust di non consentire conversioni implicite verso i booleani (a differenza di C, Python o JavaScript) rende il codice più esplicito e meno soggetto a errori. Ogni condizione deve produrre esplicitamente un valore bool, eliminando intere classi di bug legati alla “truthiness” che affliggono altri linguaggi. Questa rigidezza apparente si traduce in codice piu chiaro e affidabile.