Rust - from Mozilla

Array dinamici          

Come dice lo stesso loro nome, gli array dinamici sono strutture dati che possono vedere modificata la loro dimensione a runtime. In Rust essi vengono chiamati vectors (vettori). Nella libreria standard abbiamo il tipo vec<T> con quel T, come detto nella documentazione ufficiale, ad indicare che possiamo avere vettori di qualsiasi tipo. Nella pratica usiamo un macro per definire un vettore:

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

Come si vede i singoli elementi sono separati tra di loro con una virgola. Abbiamo creato un vettore con 3 elementi. Se vogliamo creare un vettore vuoto però, non possiamo scrivere

let v1 = vec![];

in quanto il compilatore non avrebbe le informazioni necessarie riguardo al tipo del vettore stesso. Per risolvere il problema si può ricorrere alla seguente sintassi:

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

E' anche possibile una inizializzazione rapida quando gli elementi sono tutti uguali:

let v1 = vec![0,5];

che inizializza un vettore costituito da 5 elementi tutti di valore 0.
Anche i vettori sono indicizzati in maniera sequenziale col primo indice pari a 0. L'accesso al singolo elemento avviene tramite il solito operatore [].

  Esempio 10.1
1
2
3
4
5
fn main()
{
  let v1 = vec![1,2,3,4,5];
  println!("Terzo elemento: {}", v1[2]);
}

Che ha come output il numero 3, elemento avente indice 2 nel vettore. Come è evidente infatti, per quanto detto, l'indicizzazione va vista così, per quanto riguarda il vettore definito v1:

elementi vettore v1 1 2 3 4 5
indici 0 1 2 3 4

Interessante notare che dovendo indicare esplicitamente il tipo dell'indice è necessario usare il tipo usize, il tipo intero senza segno.

let v1 = vec![1,2,3,4,5];
let x : usize = 0;
let y : i32 = 0;
println!("{}", v1[x]);
println!("{}", v1[y]);

questo codice dà errore quando si cerca di usare l'indice y.

Sempre sulla documentazione ufficiale, potrete trovare un utile esempio per fronteggiare situazioni cin cui potrebbe capitarvi di usare indici al di fuori del range definito:

let v1 = vec![1,2,3];
println!("{}", v1[3]);

Questo frammento, se mandato in esecuzione, vi restituisce un errore a runtime:

thread '<main>' panicked at 'index out of bounds: the len is 3 but the index is 3', ../src/libcollections\vec.rs:1134

e questo perchè l'indice 3 non è definito, il range per quel vettore va da 0 a 2. Per evitare questo, o meglio, gestirlo, ecco l'esempio completo:

  Esempio 10.2
1
2
3
4
5
6
7
8
9
10
11
12
fn main()
{
  let v1 = vec![1,2,3];
  match v1.get(4) {
    Some(x) => println!("Item 7 is {}", x),
    None => println!("Indice fuori range!!")
  }
  match v1.get(2) {
    Some(x) => println!("L'elemento con indice 2 vale {}", x),
    None => println!("Indice fuori range!!")
  }
}

Come per gli array statici si può usare len() per determinare la lunghezza, ovvero, il numero di elementi di un vettore:

let v1 = vec![1,2,3];
println!("{}", v1.len());

L'iterazione sugli elementi è molto semplice e può essere fatta in vari modi, per il momento li espongo in maniera rapida, tenete presente che i primi due vanno sempre bene, con gli altri potreste avere qualche sorpresa, quando li analizzeremo a fondo sarà più chiaro:

 

  Esempio 10.3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
fn main()
{
  let mut v1 = vec![1,2,3,4,5];
  for i in 0..v1.len()
  {
    print!("{} ", v1[i]);
  }
  println!("");
  for i in v1.iter()
  {
    print!("{} ", i)
  }
  println!("");
  for i in &v1
  {
    print!("{} ", i);
  }
  println!("");
  for i in &mut v1 // se v1 non è definita mut questo sistema non funziona
  {
    print!("{} ", i);
  }
  println!("");
  for i in v1
  {
    print!("{} ", i);
  }
}

Dobbiamo ora chiarire in che modo possiamo estendere (o anche ridurre) un vettore che presenta una certa forma di dinamismo rispetto alla loro controparte statica. Ci sono due utili metodi, ovvero push(elemento) e pop().

  Esempio 10.4
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
fn main()
{
  let mut v1 = vec![1,2,3];
  for i in v1.iter()
  {
    print!("{} ", i)
  }
  v1.push(4);
  println!("");
  for i in v1.iter()
  {
    print!("{} ", i)
  }
  v1.pop();
  println!("");
  for i in v1.iter()
  {
    print!("{} ", i)
  }
}

Ovviamente il vettore deve essere definito mut affinchè possa essere modificato. Ve ne stavate dimenticando, vero? Eseguendo questo piccolo programma vedrete come un elemento, il numero 4, viene aggiunto, per effetto dell'istruzione push alla riga 8, e poi tolto, operazione compiuta da pop alla 14.

 

Relativamente agli array c'è ancora moltissimo da dire, questo capitolo è un work in progress.