Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

Rust: array, tuple, vettori e slice

Array, tuple, vettori e slice: una panoramica dedicata alla gestione delle "collezioni" di elementi nella programmazione in Rust
Array, tuple, vettori e slice: una panoramica dedicata alla gestione delle "collezioni" di elementi nella programmazione in Rust
Link copiato negli appunti

Questa lezione propone una visione orientativa sui costrutti Rust dedicati alla gestione delle "collezioni" di elementi. Scopriremo che, al di là di alcune somiglianze, array, vettori, tuple e slice sono tutti diversi tra loro in quanto a natura e finalità.

Array in Rust

Gli array sono sequenze a dimensione fissa di elementi omogenei vale a dire dello stesso tipo. Gli array vengono dichiarati e manipolati tramite parentesi quadre ma, come ogni variabile, al momento della dichiarazione sono immutabili (a meno che non usiamo mut). Lavoriamoci un po':

# (1) dichiarazione di un array
let numeri=[1,2,3,4,5];
# (2) lunghezza dell'array con len
println!("L'array contiene {} numeri", numeri.len());
# (3) estrazione dei valori con parentesi quadre
println!("Il primo è {} e l'ultimo {}", numeri[0], numeri[4]);
println!("Elenco dei numeri nell'array:");
# (4) iterazione con iter
for n in numeri.iter(){
    println!(">>> {}", n);
}

Con queste righe di codice sperimentiamo:

  1. dichiarazione esplicita dell'array con valori tra parentesi quadre;
  2. estrapolazione della lunghezza dell'array con l'apposita funzione len;
  3. estrazione di valori indicando la relativa posizione (contata a partire da zero) tra parentesi quadre;
  4. impiego di un iteratore, fornito dalla funzione iter, per avviare un attraversamento continuo di tutti i valori collocati nell'array.

Ecco l'output:

L'array contiene 5 numeri
Il primo è 1 e l'ultimo 5
Elenco dei numeri nell'array:
>>> 1
>>> 2
>>> 3
>>> 4
>>> 5

L'unica cosa che non potremmo fare con questo array è modificarne i valori in quanto immutabile. Se volessimo apportare modifiche, sarebbe sufficiente usare le parentesi quadre per indicare l'elemento cui assegnare un nuovo valore applicando però mut alla dichiarazione:

# array dichiarato con mut
let mut numeri=[1,2,3,4,5];
# riassegnazione del quarto valore
numeri[3] = 99;

Dagli array ai vettori in Rust

Con i vettori otteniamo invece una forma dinamica ed espandibile di array, istanziabile mediante la macro vec! o direttamente con il tipo standard Vec<T> dove la T tra parentesi angolari indica il tipo di dato gestito (si tratta dei cosiddetti Generics, costrutti che studieremo più avanti in questa stessa guida). Si può creare un vettore inizializzato con:

let vettore = vec![1, 2, 3];

o uno totalmente nuovo (e vuoto) con:

let vettore: Vec<i32> = Vec::new();

in cui indichiamo anche il tipo esplicito degli elementi.

Vediamo un esempio in cui partiamo da un vettore vuoto (mutabile grazie a mut per permetterne la modifica) e lo riempiamo con la tabellina relativa al numero indicato nella variabile tabellina. Come si vede, a parte la dichiarazione del costrutto e l'uso della funzione push per aggiungere elementi in coda, per il resto, tutto quello che facciamo segue quanto già appreso con gli array:

# creiamo un vettore mutabile
let mut vettore: Vec&lt;i32&gt; = Vec::new();
let tabellina = 5;
# inseriamo i valori della tabellina uno alla volta
for i in 1..=10{
    vettore.push(i*tabellina);
}
# estraiamo la lunghezza del vettore con len
println!(&quot;Il vettore contiene {} valori&quot;, vettore.len());
# accesso agli elementi con parentesi quadre
println!("Il primo valore contiene {}", vettore[0]);
# iterazione sugli elementi
for n in vettore.iter(){
    println!(&quot;{}&quot;, n);
}

Ecco l'output che otteniamo:

Il vettore contiene 10 valori
Il primo valore contiene 5
5
10
15
20
25
30
35
40
45
50

Tuple in Rust

Le tuple si dichiarano tra parentesi tonde e generalmente raccolgono tipi eterogenei ovvero tipi potenzialmente diversi tra loro. Mentre array e vettori sono ideali per rappresentare l'evoluzione di un fenomeno (esempio: le quotazioni giornaliere di uno stesso titolo azionario, le temperature registrate nella medesima città), le tuple sono molto utili per rappresentare più aspetti di uno stesso campione come una riga di risultati di un'interrogazione ad un database.

Supponiamo che ci vengano restituiti i dati di un certo Giovanni Rossi, 32 anni, automunito. I campi di una tupla che lo rappresentano potrebbero essere:

let risultati=("Giovanni", "Rossi", 32, true);

Un singolo elemento della tupla può essere recuperato con il numero di posizione (che si conta a partire da 0) separato dal nome della tupla da un punto. Ad esempio, il primo valore della tupla si troverebbe in risultati.0. Altrimenti si potrebbe procedere ad una deserializzazione della tupla assegnando, in ordine, ogni valore ad una variabile:

let (nome, cognome, eta, automunito)= risultati;
println!("Nome: {}", nome);
println!("Cognome: {}", cognome);
println!("Età: {}", eta);
println!("Automunito: {}", if automunito {"Sì"} else {"No"});

ottenendo in output:

Primo valore: Giovanni
Nome: Giovanni
Cognome: Rossi
Età: 32
Automunito: Sì

Slice in Rust

Una slice non è una struttura dati autonoma ma una sorta di view, di focus, su una porzione contigua di elementi di un array o di un vettore. Lo scopo di una slice è permettere di attivare azioni sugli elementi che indica senza costringere a farne una copia. Supponiamo di avere il seguente array di numeri:

let numeri=[5,8,21,3,97,56,12,45,6,2];

Possiamo definire una slice che rappresenti i suoi valori a partire da quello di indice 3 arrivando fino a quello di indice 7:

let alcuni_numeri= &numeri[3..=7];
for n in alcuni_numeri.iter(){
    println!("{}", n);
}
Ecco l'output restituito:

3
97
56
12
45

La slice si definisce con un simbolo & che precede nome dell'array/vettore e parentesi quadre con all'interno gli estremi dell'intervallo.

E ora?

Acquisite queste informazioni sulle strutture dati, ora cosa ne facciamo? Dobbiamo iniziare a sperimentarle impiegandole nei nostri programmi ma sempre scegliendo, per ognuna, i casi d'uso più adatti. Soprattutto dovremo imparare a gestire reti di informazioni articolate per strutturare le architetture dei nostri progetti.

Ti consigliamo anche