如何通过副作用实现变量增量?

hxw*_*ker 4 side-effects rust

出于学习目的,我尝试了这个解决方案,但它不起作用:

use std::ops::Add;

fn inc<T: Add>(x:&mut T) {
    *x += 1; 
}

fn main() {
    let mut x:i32 = 10;
    let mut y:u8 = 1;
    inc(&mut x);
    inc(&mut y);
    println!("{} {}", x, y);
}
Run Code Online (Sandbox Code Playgroud)

错误信息:

<anon>:4:5: 4:7 error: binary assignment operation `+=` cannot be applied to types `T` and `_` [E0368]
<anon>:4     *x += 1; 
             ^~
<anon>:4:5: 4:7 help: see the detailed explanation for E0368
error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

这样做的正确方法是什么?

Chr*_*gan 5

目前,+=只定义了原始整数类型; 通常,您需要将其扩展为*x = *x + 1;.这显示出更多问题:

<anon>:4:15: 4:16 error: mismatched types:
 expected `T`,
    found `_`
(expected type parameter,
    found integral variable) [E0308]
<anon>:4     *x = *x + 1; 
                       ^
<anon>:4:10: 4:16 error: mismatched types:
 expected `T`,
    found `<T as core::ops::Add>::Output`
(expected type parameter,
    found associated type) [E0308]
<anon>:4     *x = *x + 1; 
                  ^~~~~~
error: aborting due to 2 previous errors
Run Code Online (Sandbox Code Playgroud)

让我们看一下Add特质的定义:

pub trait Add<RHS = Self> {
    /// The resulting type after applying the `+` operator
    type Output;

    /// The method for the `+` operator
    fn add(self, rhs: RHS) -> Self::Output;
}
Run Code Online (Sandbox Code Playgroud)

因此Self + RHS产生一个类型的对象<Self as Add<RHS>>::Output.

当您将值存回时*x,计算结果必须为a T; 因此,我们建立了约束的T需要不Add但是.Add<???, Output = T>

那将???是什么?是什么类型的1?它不是通用的; 它的10种已知的基本整数类型之一(isize,i8,i16,i32,i64,usize,u8,u16,u32,u64).这显然是行不通的,因为整型不执行另外较小的类型,默认值对RHSSelf(也就是,其中T: Add表示T: Add<Self>)是所有你可以指望,但1不能是类型T.

解决方案是使用生成值1的通用函数.来自crates.io std::num::Onenum箱子里有一个不稳定的,一个稳定的num::One.使用前者需要每晚使用Rust,使用后者需要删除std::,添加extern crate num;并添加num到Cargo.toml依赖项部分.

我们还需要一个Copy绑定,允许*x*x + 1工作.

这是最终结果:

#![feature(zero_one)]

use std::ops::Add;
use std::num::One;

fn inc<T: Copy + One + Add<T, Output = T>>(x: &mut T) {
    *x = *x + T::one(); 
}

fn main() {
    let mut x: i32 = 10;
    let mut y: u8 = 1;
    inc(&mut x);
    inc(&mut y);
    println!("{} {}", x, y);
}
Run Code Online (Sandbox Code Playgroud)