In Rust, what is the idiomatic equivalent of Haskell's [n..m]?
It is now possible to use ..
in Rust:
let vec: Vec<_> = (n .. m + 1).collect();
gives you a Vec
from all the numbers from n
to m
.
As noted in the comment by Shepmaster, beware, it will not work if you need a range up to the maximum value of the type (255
for u8
).
Note that this answer pertains to a pre-1.0 version of Rust and does not apply for 1.0. Specifically,
Vec::from_fn
was removed.
There's probably nothing really idiomatic as of now. There is a handful of convenience functions to construct vectors, for example you can use Vec::from_fn
:
Vec::from_fn(m+1-n, |i| i+n)
Note that this answer pertains to a pre-1.0 version of Rust and does not apply for 1.0. Specifically,
std::iter::range
andstd::iter::range_inclusive
were removed.
As of Rust 1.0.0-alpha, the easiest way to accomplish this is to use the convenience functions provided in the module std::iter
: range
and range_inclusive
, which return iterators generating a list of numbers in the range [low, high) or [low, high], respectively.
In addition, you can build a vector from an iterator using the collect
method:
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<_>>());
Note that the return value of collect
has its type explicitly specified in both its uses above. Normally, the Rust compiler can infer the types of expressions without an explicit specification, but collect
is one of the most common cases for which the type cannot be fully inferred, in this case because it can't infer a concrete type that implements the trait FromIterator<A>
, the return type of collect
.
The type of a generic return value can be specified either as an explicit type in a let
definition statement or inline by using the function::<Type>()
syntax. Since inference fails only due to not knowing a concrete type implementing FromIterator<A>
, it's possible, when explicitly specifying a generic type, to leave "holes" for type arguments which will be inferred, signified by _
. This is done with the second call to collect
above—in the expression Vec<_>
, it's explicitly specified that the container receiving elements from collect
is a Vec<T>
, but the compiler figures out what exact type T
must be. Currently, integers whose types are left unspecified and can't be inferred fall back to i32
(32-bit machine integer) as a default.