I am trying to write a Rust function that is similar to the built-in Range
, but I want something that will return only X numbers, and return it as a list, which is why I'm trying to make this function:
extern crate num;
use num::Integer;
fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> {
(0..len).map(|i| start + step * i).collect()
}
fn main() {
println!("{:?}", positions(10, 2, 10));
}
Except I am getting a compiler error:
error[E0308]: mismatched types
--> src/main.rs:6:9
|
6 | (0..len).map(|i| start + step * i).collect()
| ^^^ expected integral variable, found type parameter
|
= note: expected type `{integer}`
found type `T`
= help: here are some functions which might fulfill your needs:
- .div_floor(...)
- .gcd(...)
- .lcm(...)
- .mod_floor(...)
error[E0308]: mismatched types
--> src/main.rs:6:37
|
6 | (0..len).map(|i| start + step * i).collect()
| ^ expected type parameter, found integral variable
|
= note: expected type `T`
found type `{integer}`
The problem is
0
. I'm unclear on the exact rules right now, but let's be general:0
is of some specific integer type, which may or may not be the same thing as whateverT
is. Thus, the compiler can't work out what the type parameter torange
is supposed to be.You can resolve this by using
Zero::zero
:This gives the compiler enough leeway to infer that the two arguments to
range
are of the same type. However, that's still not enough to useRange
as an iterator:Unfortunately, as of Rust 1.17, the
Step
trait is unstable, so there's currently no good way to solve this problem using stable Rust.Using unstable Rust, you can require implementations of
Step
:You also need to require that
T
can be copied (or cloned, if you like) because the implementation ofAdd
andMul
consumes the operands by value, which would mean thatstart + step * i
could only be called once, except it needs to be called multiple times.