如何通过副作用实现变量增量?
How to implement variable increment via side effect?
出于学习目的,我尝试了这个解决方案,但是 it does not work:
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);
}
错误信息:
<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
正确的做法是什么?
目前,+=
仅在原始整数类型上定义;通常,您需要将其扩展为 *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
让我们看看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;
}
因此 Self + RHS
生成一个类型为 <Self as Add<RHS>>::Output
的对象。
当您将值存储回 *x
时,计算结果必须是 T
;因此我们确定 T
上的界限需要不是 Add
而是 Add<<em>???</em>, Output = T>
.
那么,<em>会是什么???</em>
会是什么? 1
的类型是什么?这不是通用的;它是十种已知原始整数类型之一(isize
、i8
、i16
、i32
、i64
、usize
、u8
, u16
, u32
, u64
)。这显然行不通,因为整数类型不实现较小类型的加法——RHS
的默认值 Self
(即,T: Add
表示 T: Add<Self>
) 是您可以指望的全部,但是 1
不能是 T
.
类型
解决方案是使用生成值 1 的通用函数。 std::num::One
中有一个不稳定的,crates.io、num::One
的 num
箱子中有一个稳定的。使用前者需要 Rust nightly,使用后者需要删除 std::
,添加 extern crate num;
并将 num
添加到 Cargo.toml 依赖项部分。
我们还需要一个 Copy
绑定来允许 *x + 1
的 *x
工作。
#![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);
}
出于学习目的,我尝试了这个解决方案,但是 it does not work:
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);
}
错误信息:
<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
正确的做法是什么?
目前,+=
仅在原始整数类型上定义;通常,您需要将其扩展为 *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
让我们看看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;
}
因此 Self + RHS
生成一个类型为 <Self as Add<RHS>>::Output
的对象。
当您将值存储回 *x
时,计算结果必须是 T
;因此我们确定 T
上的界限需要不是 Add
而是 Add<<em>???</em>, Output = T>
.
那么,<em>会是什么???</em>
会是什么? 1
的类型是什么?这不是通用的;它是十种已知原始整数类型之一(isize
、i8
、i16
、i32
、i64
、usize
、u8
, u16
, u32
, u64
)。这显然行不通,因为整数类型不实现较小类型的加法——RHS
的默认值 Self
(即,T: Add
表示 T: Add<Self>
) 是您可以指望的全部,但是 1
不能是 T
.
解决方案是使用生成值 1 的通用函数。 std::num::One
中有一个不稳定的,crates.io、num::One
的 num
箱子中有一个稳定的。使用前者需要 Rust nightly,使用后者需要删除 std::
,添加 extern crate num;
并将 num
添加到 Cargo.toml 依赖项部分。
我们还需要一个 Copy
绑定来允许 *x + 1
的 *x
工作。
#![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);
}