无法创建使用文字零的通用函数

2024-04-08

我正在尝试编写一个与内置函数类似的 Rust 函数Range,但我想要的东西只会返回 X 个数字,并将其作为列表返回,这就是我尝试创建此函数的原因: 外部板条箱编号;

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 https://docs.rs/num/0.1.37/num/trait.Zero.html:

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 https://doc.rust-lang.org/std/iter/trait.Step.html不稳定,所以目前没有好的方法使用稳定的 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));
}

You also需要要求T可以复制(或克隆,如果你愿意的话),因为Add and Mul按值消耗操作数,这意味着start + step * i只能调用一次,除非需要调用多次。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法创建使用文字零的通用函数 的相关文章

随机推荐