前言
由于 ops 中的很多 trait 功能类似,所以就不一个一个来了。本篇文章以最短的篇幅概括 std::ops 中还未提及的主要知识点。
运算符重载
最基础的就是对四则运算之类的操作符进行重载了。这里借用计算点坐标的例子来演示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
extern crate hello_rust;
use std::ops::Add;
#[derive(Debug, Clone, Copy)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Self;
fn add(self, rhs: Point) -> Self {
Self {
x: self.x + rhs.x,
y: self.y + rhs.y,
}
}
}
fn main() {
println!("{:?}", Point { x: 1, y: 2 } + Point { x: 2, y: 1 });
}
|
FnOnce/FnMut/Fn
Rust 中用 fn 可以定义函数,而 Fn 可以对函数做抽象。三种不同形态对应 self 参数的传递类型。FnOnce 对应 move 传递,这样的函数不能执行多次,所以签名带了个 Once。FnMut/Fn 分别对应 &mut Self 和 &Self 类型:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
pub trait FnOnce<Args> {
type Output;
pub extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
pub trait FnMut<Args>: FnOnce<Args> {
pub extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
pub trait Fn<Args>: FnMut<Args> {
pub extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
let x = String::from("x");
let consume_and_return_x = move || x; // FnOnce() -> String
let mut square_x = || x *= x; // FnMut()
let double = |x| x * 2; // Fn()
|
编译器在自动为闭包实现 trait 的时候会先试 Fn 不行再 FnMut 最后 FnOnce。
文档中特别提到如果 F 实现了 Fn 那么自动 &F 也实现了 Fn。这句话我们可以利用下面的例子来感受一下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
extern crate hello_rust;
fn test_fn<T>(f: &T)
where
T: Fn(),
{
f();
}
fn main() {
let a = || println!("hello world");
test_fn(&a);
}
|
Range 语法
Range 语法总共六种形态:
1
2
3
4
5
6
7
8
9
10
11
12
|
extern crate hello_rust;
fn main() {
let arr = [0, 1, 2, 3];
assert_eq!([0, 1, 2, 3], arr[..]);
assert_eq!([1, 2, 3], arr[1..]);
assert_eq!([0, 1], arr[..2]);
assert_eq!([0, 1, 2], arr[..=2]);
assert_eq!([1], arr[1..2]);
assert_eq!([1, 2], arr[1..=2]);
}
|