无法创建使用文字零的通用函数 [英] Cannot create a generic function that uses a literal zero

查看:26
本文介绍了无法创建使用文字零的通用函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写一个类似于内置 Range 的 Rust 函数,但我想要一些只返回 X 数字的东西,并将其作为列表返回,这就是为什么我正在尝试制作此功能:外部板条箱编号;

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}`

推荐答案

问题是0.我现在不清楚确切的规则,但让我们概括一下:0 是某种特定的整数类型,它可能与任何 T 相同,也可能不同是.因此,编译器无法计算出 range 的类型参数应该是什么.

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 whatever T is. Thus, the compiler can't work out what the type parameter to range is supposed to be.

您可以使用 Zero::zero 解决此问题:

You can resolve this by using 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 作为迭代器仍然不够:

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 use Range as an iterator:

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 来解决这个问题的好方法.

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,你可以要求 Step 的实现:

Using unstable Rust, you can require implementations of 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 的实现>Mul 按值消耗操作数,这意味着 start + step * i 只能调用一次,除非需要多次调用.

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.

这篇关于无法创建使用文字零的通用函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆