无法创建使用文字零的通用函数
Cannot create a generic function that uses a literal zero
我正在尝试编写一个类似于内置 Range
的 Rust 函数,但我想要的东西 return 只有 X 个数字,并且 return 它作为一个列表,这就是为什么我要尝试实现此功能的原因:
外部板条箱编号;
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));
}
除了我遇到编译器错误:
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}`
问题是0
。我现在不清楚确切的规则,但让我们概括一下:0
是某种特定的整数类型,它可能与 T
是同一类型,也可能不同。因此,编译器无法确定 range
的类型参数应该是什么。
您可以使用 Zero::zero
:
解决此问题
fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> {
(T::zero()..len).map(|i| start + step * i).collect()
}
这为编译器提供了足够的余地来推断 range
的两个参数属于同一类型。但是,这仍然不足以将 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`
不幸的是,从 Rust 1.17 开始,Step
trait 不稳定,因此目前没有使用稳定的 Rust 解决此问题的好方法。
使用不稳定的 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));
}
你也需要要求T
可以被复制(或者克隆,如果你喜欢的话)因为Add
和[=24的实现=] 按值消耗操作数,这意味着 start + step * i
只能被调用一次,除非它需要被调用多次。
我正在尝试编写一个类似于内置 Range
的 Rust 函数,但我想要的东西 return 只有 X 个数字,并且 return 它作为一个列表,这就是为什么我要尝试实现此功能的原因:
外部板条箱编号;
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));
}
除了我遇到编译器错误:
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}`
问题是0
。我现在不清楚确切的规则,但让我们概括一下:0
是某种特定的整数类型,它可能与 T
是同一类型,也可能不同。因此,编译器无法确定 range
的类型参数应该是什么。
您可以使用 Zero::zero
:
fn positions<T: Integer>(start: T, step: T, len: T) -> Vec<T> {
(T::zero()..len).map(|i| start + step * i).collect()
}
这为编译器提供了足够的余地来推断 range
的两个参数属于同一类型。但是,这仍然不足以将 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`
不幸的是,从 Rust 1.17 开始,Step
trait 不稳定,因此目前没有使用稳定的 Rust 解决此问题的好方法。
使用不稳定的 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));
}
你也需要要求T
可以被复制(或者克隆,如果你喜欢的话)因为Add
和[=24的实现=] 按值消耗操作数,这意味着 start + step * i
只能被调用一次,除非它需要被调用多次。