Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Rust, what is the idiomatic equivalent of Haskell's [n..m]? [duplicate]

Tags:

rust

How do I produce a list containing all the integers in Rust? I'm looking for the equivalent of Haskell's [n..m] or Python's range(n, m+1) but can't find anything.

I'm aware of the int::range function and thought it was what I was looking for, but it is made to iterate over a range, not to produce it.

like image 656
Fabien Avatar asked Apr 05 '13 14:04

Fabien


4 Answers

It is now possible to use ..= in Rust:

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

gives you a Vec from all the numbers from n to m.

..= is the inclusive range operator, whereas .. is exclusive.

like image 162
antoyo Avatar answered Nov 10 '22 21:11

antoyo


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)
like image 35
ben Avatar answered Nov 10 '22 23:11

ben


Note that this answer pertains to a pre-1.0 version of Rust and does not apply for 1.0. Specifically, std::iter::range and std::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.

like image 8
telotortium Avatar answered Nov 10 '22 21:11

telotortium


Since Rust 1.26.0 you can use the RangeToInclusive (..=) operator to generate an inclusive range.

let v: Vec<_> = (n..=m).collect()
like image 7
belst Avatar answered Nov 10 '22 22:11

belst