Rust - from Mozilla

Range      

Un range è semplicemente una sequenza ininterrotta di valori interi. La definizione è semplicissima:

let r1 = 0..10;

Ecco definito un range di nome r1.

  Esempio 14.1
1
2
3
4
5
6
7
8
fn main()
{
  let r1 = 0..10;
  for x in r1
  {
    println!("{}", x);
  }
}

L'esempio 14.1 stampa a video tutti i numeri da 0 a 9. Questo significa che l'estremo superiore, 10, resta escluso. E' importante ricordare questo fatto, ovvero che un range definito nell'intervallo x1..x2 lavora su x1..x2-1.
Da un punto di vista interno un range è definito come segue:

pub struct Range<Idx> {
pub start: Idx,
pub end: Idx,
}

e quindi evidenzia due proprietà: start ed end. E'anche presente il metodo len() che ne restituisce la lunghezza, ovvero il numero esatto di volte che potremo iterare sul range (quindi da 0 a 10 sarà 10 e non 11, per quanto detto).

  Esempio 14.2
1
2
3
4
5
6
7
fn main()
{
  let r1 = 0..10;
  println!("{}", r1.len());
  println!("{}", r1.count()); // count() equivale a len()
  println!("{}", r1.start);
  println!("{}", r1.end);
}

Per trovare i massimi ed i minimi di un range abbiamo max e min che restituiscono una Option per cui vanno trattati ad esempio come segue (min funziona in maniera del tutto analoga a max, mostrato nell'esempio):

  Esempio 14.3
1
2
3
4
5
6
7
8
9
10
fn main()
{
  let r1 = 0..10;
  println!("{}", r1.len());
  let x = r1.max();
  match x {
    Some(x) => println!("{}", x),
    None => println!("Vuoto"),
  }
}


Tornando all'esempio 14.1 attenzione ad un particolare: il range r1 viene "trascinato" nello scope delimitato dal for e quindi non sarà più visibile all'esterno una volta attratto nel ciclo che inizia alla riga 4. Provando infatti ad usare le istruzioni dell'esempio 14.2 dopo la fine del for porterebbe ad un errore in compilazione. That's Rust, un po' strano per chi viene da altri linguaggi ma in realtà dietro a tutto c'è un meccanismo che impareremo a conoscere più avanti, per il momento è argomento un po' troppo avanzato. Quindi il problema a questo punto è: come gestisco la cosa? Una soluzione la trovate nel seguente esempio:

  Esempio 14.4
1
2
3
4
5
6
7
8
9
fn main()
{
  let r1 = 0..10;
  for x in r1.clone()
  {
    println!("{}", x)
  }
  println!("{}", r1.len());
}

il metodo position() invece restituisce l'indice di un elemento. Anche qui siamo di fronte ad option come valore di ritorno:

  Esempio 14.5
1
2
3
4
5
6
7
8
9
10
fn main()
{
  let mut r1 = 1..10;
  let y = r1.position(|x| x == 34);
  match y
  {
    Some(y) => println!("{}", y),
    None => println!("Not found"),
  }
}

Tanti altri metodi si possono trovare sulla pagina ufficiale (non proprio un esempio di chiarezza, a parer mio)

E' possibile definre un range anche siffatto:

r1 = 'a'..'z';

per il quale valgono le proprietà start e end ma non len(). Come da documentazione, per un range di caratteri non è presente il metodo len(), come d'altra parte vi suggerirà il compilatore. Questo è Rust.

Esistono poi una serie di proprietà che potrebbero essere utili ma, al momento, sono tutte marcate "unstable". 

Inoltre il compilatore comprende anche una interessante sintassi relativa ad un range inclusivo, comprendente cioè anche l'ultimo elemento, ovvero:
x1...x2
con 3 punti invece di 2. Tale operatore al momento in cui scrivo e cioè con la versione 1.20 del linguaggio, è marcato come "sperimentale" e non compila....

Completerò questo paragrafo man mano che la situazione si stabilizzerà....