2013-04-05 16 views
14

Come si produce una lista contenente tutti gli interi in Rust? Sto cercando l'equivalente di Haskell [n..m] o Python range(n, m+1) ma non riesco a trovare nulla.In Rust, qual è l'equivalente idiomatico di Haskell [n..m]?

Sono a conoscenza della funzione int::range e ho pensato che fosse quello che stavo cercando, ma è fatto per scorrere su un intervallo, non per produrlo.

+1

Si noti che a causa della valutazione lenta di Haskell, il suo tipo di elenco di fatto consiste in un elemento e una funzione per continuare a produrre il resto dell'elenco (ad esempio, l'elemento successivo e la funzione * next * e così via), il che significa che in molti modi i tipi di 'Iterator' di Rust sono in effetti semanticamente una corrispondenza più stretta per' [a] 'di Haskell di' Vec '. – glaebhoerl

risposta

7

Nota che questa risposta si riferisce ad una versione pre-1.0 di ruggine e non si applica per i 1.0. Nello specifico, sono stati rimossi std::iter::range e std::iter::range_inclusive.

Al ruggine 1.0.0-alpha, il modo più semplice per ottenere questo risultato è quello di utilizzare le funzioni fornite nel modulo std::iter: range e range_inclusive, che restituiscono iteratori generando un elenco di numeri nell'intervallo [bassa , alto) o [basso, alto], rispettivamente.

Inoltre, è possibile costruire un vettore da un iteratore utilizzando il metodo collect:

use std::iter::range_inclusive; 
let first_hundred: Vec<i32> = range_inclusive(1, 100).collect(); 
println!("upper bound inclusive: {:?}, exclusive: {:?}", 
     first_hundred, 
     range(101, 201).collect::<Vec<_>>()); 

Si noti che il valore di ritorno di collect ha il suo tipo esplicitamente specificato in entrambi i suoi usi di cui sopra. Normalmente, il compilatore Rust può inferire i tipi di espressioni senza una specifica esplicita, ma collect è uno dei casi più comuni per i quali il tipo non può essere dedotto completamente, in questo caso perché non può dedurre un tipo concreto che implementa il tratto FromIterator<A>, il tipo di ritorno di collect.

Il tipo di un valore restituito generico può essere specificato come un tipo esplicito in una definizione di definizione let o in linea utilizzando la sintassi function::<Type>(). Poiché l'inferenza non riesce solo a causa della mancata conoscenza di un tipo concreto che implementa FromIterator<A>, è possibile, quando si specifica esplicitamente un tipo generico, lasciare "buchi" per argomenti tipo che verranno dedotti, identificati da _. Ciò avviene con la seconda chiamata collect sopra — nell'espressione Vec<_>, è esplicitamente specificato che il contenitore che riceve elementi da collect è un Vec<T>, ma il compilatore capisce quale tipo esatto T deve essere. Attualmente, gli interi i cui tipi sono lasciati non specificati e non possono essere dedotti ricadono come valori predefiniti su i32 (numero intero macchina a 32 bit).

10

Nota che questa risposta si riferisce a una pre-versione 1.0 di ruggine e non si applica per i 1.0. In particolare, è stato rimosso Vec::from_fn.

Probabilmente non c'è nulla di veramente idiomatico al momento. C'è una manciata di funzioni comfort per costruire vettori, per esempio, si può utilizzare Vec::from_fn:

Vec::from_fn(m+1-n, |i| i+n) 
+0

Grazie! Lo userò. – Fabien

+0

Troverai Counter un po 'più idiomatico. http://static.rust-lang.org/doc/std/iterator.html#struct-counter – dcolish

12

E 'ora possibile utilizzare .. a Rust:

let vec: Vec<_> = (n .. m + 1).collect(); 

ti dà una Vec da tutti i numeri n-m.

Come notato nel commento di Shepmaster, attenzione, non funzionerà se è necessario un intervallo fino al valore massimo del tipo (255 per u8).

+6

* a 'm' incluso * - pedanticamente, non è veramente inclusivo. Ad esempio, non esiste un modo semplice per ottenere tutti i valori di 'u8' da 0 a 255. Esistono vari RFC che si muovono attorno a cui si propone di aggiungere un operatore di intervallo inclusivo. – Shepmaster

+1

Anche questo può essere scritto come 'let vec = Vec :: from_iter (n .. m + 1)'. – malbarbo

Problemi correlati