[英]Cannot create a generic function that uses a literal zero
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; 我试图编写一个与内置
Range
相似的Rust函数,但是我想要只返回X个数字并将其作为列表返回的东西,这就是为什么我要创建此函数的原因: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
. 问题是
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 whatever T
is. 我目前尚不清楚确切的规则,但让我们大致概括一下:
0
是某些特定的整数类型,它与T
可能相同也可能不同。 Thus, the compiler can't work out what the type parameter to range
is supposed to be. 因此,编译器无法计算出要设定
range
的类型参数。
You can resolve this by using Zero::zero
: 您可以使用
Zero::zero
解决此问题:
fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> {
(T::zero()..len).map(|i| start + step * i).collect()
}
This gives the compiler enough leeway to infer that the two arguments to range
are of the same type. 这为编译器提供了足够的空间来推断
range
的两个参数是同一类型。 However, that's still not enough to use Range
as an iterator: 但是,这还不足以将
Range
用作迭代器:
error: no method named `map` found for type `std::ops::Range<T>` in the current scope
--> src/main.rs:8:22
|
8 | (T::zero()..len).map(|i| start + step * i).collect()
| ^^^
|
= note: the method `map` exists but the following trait bounds were not satisfied: `T : std::iter::Step`, `&'a T : std::ops::Add`, `std::ops::Range<T> : std::iter::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. 不幸的是,从Rust 1.17开始,
Step
trait是不稳定的,因此,目前没有使用稳定的Rust解决此问题的好方法。
Using unstable Rust, you can require implementations of Step
: 使用不稳定的Rust,您可能需要实现以下
Step
:
#![feature(step_trait)]
extern crate num;
use num::Integer;
fn positions<T>(start: T, step: T, len: T) -> Vec<T>
where T: Integer + std::iter::Step + Copy,
for<'a> &'a T: std::ops::Add<Output = T>
{
(T::zero()..len).map(|i| start + step * i).collect()
}
fn main() {
println!("{:?}", positions(10, 2, 10));
}
You also need to require that T
can be copied (or cloned, if you like) because the implementation of Add
and Mul
consumes the operands by value, which would mean that start + step * i
could only be called once, except it needs to be called multiple times. 您还需要要求可以复制(或克隆,如果愿意的话)
T
,因为Add
和Mul
的实现按值消耗操作数,这意味着start + step * i
只能被调用一次,除非它需要被多次调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.