RUST Option类型标准库代码分析
代码路径:
%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\option.rs
Option的方法源代码如下:
impl<T> Option<T> { | |
pub const fn is_some(&self) -> bool { | |
matches!(*self, Some(_)) | |
} | |
pub const fn is_none(&self) -> bool { | |
!self.is_some() | |
} | |
//通过此函数来做包装后和包装前的值是否相等的判断 | |
pub fn contains<U>(&self, x: &U) -> bool | |
where | |
U: PartialEq<T>, | |
{ | |
match self { | |
Some(y) => x == y, | |
None => false, | |
} | |
} | |
//当希望获取Option封装的变量的借用的时候,使用这个函数 | |
//因为Option可能为None,所以返回值只能是Option<&T> | |
pub const fn as_ref(&self) -> Option<&T> { | |
match *self { | |
Some(ref x) => Some(x), | |
None => None, | |
} | |
} | |
//类似于as_ref,但返回的是可变引用 | |
pub const fn as_mut(&mut self) -> Option<&mut T> { | |
match *self { | |
Some(ref mut x) => Some(x), | |
None => None, | |
} | |
} | |
//解封装函数,None时输出指定的错误信息并退出程序 | |
pub fn expect(self, msg: &str) -> T { | |
match self { | |
Some(val) => val, | |
None => expect_failed(msg), | |
} | |
} | |
//解封装函数,None时输出固定的错误信息并退出程序 | |
pub const fn unwrap(self) -> T { | |
match self { | |
Some(val) => val, | |
None => panic!("called `Option::unwrap()` on a `None` value"), | |
} | |
} | |
//解封装,None时返回给定的默认值 | |
pub fn unwrap_or(self, default: T) -> T { | |
match self { | |
Some(x) => x, | |
None => default, | |
} | |
} | |
//解封装,None时调用给定的闭包函数 | |
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T { | |
match self { | |
Some(x) => x, | |
None => f(), | |
} | |
} | |
//确认不会为None时的解封装 | |
pub unsafe fn unwrap_unchecked(self) -> T { | |
debug_assert!(self.is_some()); | |
match self { | |
Some(val) => val, | |
// SAFETY: the safety contract must be upheld by the caller. | |
None => unsafe { hint::unreachable_unchecked() }, | |
} | |
} | |
//主要用于函数式编程,在不解封装的情况下对Option的值进行处理,并按需要返回适合的类型 | |
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { | |
match self { | |
Some(x) => Some(f(x)), | |
None => None, | |
} | |
} | |
//同上,None时返回默认值 | |
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U { | |
match self { | |
Some(t) => f(t), | |
None => default, | |
} | |
} | |
//同上,None时调用默认闭包函数 | |
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { | |
match self { | |
Some(t) => f(t), | |
None => default(), | |
} | |
} | |
//将Option转换为Result,也是为支持函数式编程 | |
pub fn ok_or<E>(self, err: E) -> Result<T, E> { | |
match self { | |
Some(v) => Ok(v), | |
None => Err(err), | |
} | |
} | |
//同上,None时调用默认函数处理 | |
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> { | |
match self { | |
Some(v) => Ok(v), | |
None => Err(err()), | |
} | |
} | |
//主要还是应用于函数式编程,值是Some(x)的时候返回预设值 | |
pub fn and<U>(self, optb: Option<U>) -> Option<U> { | |
match self { | |
Some(_) => optb, | |
None => None, | |
} | |
} | |
//主要用于函数式编程,与and 形成系列,值为Some(x)调用函数并返回函数值 | |
pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> { | |
match self { | |
Some(x) => f(x), | |
None => None, | |
} | |
} | |
//如果是Some(x), 判断是否满足预设条件 | |
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self { | |
if let Some(x) = self { | |
if predicate(&x) { | |
return Some(x); | |
} | |
} | |
None | |
} | |
//如果是Some(x)返回本身,如果是None,返回预设值 | |
pub fn or(self, optb: Option<T>) -> Option<T> { | |
match self { | |
Some(_) => self, | |
None => optb, | |
} | |
} | |
//如果是Some(x)返回本身,否则返回预设函数 | |
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> { | |
match self { | |
Some(_) => self, | |
None => f(), | |
} | |
} | |
//类似xor操作 | |
pub fn xor(self, optb: Option<T>) -> Option<T> { | |
match (self, optb) { | |
//一方为Some,一方为None,返回Some值 | |
(Some(a), None) => Some(a), | |
(None, Some(b)) => Some(b), | |
//两者都为Some,或两者都为None, 返回None | |
_ => None, | |
} | |
} | |
//对Option设置一个值,此时原有的值会被drop掉 | |
//例子:let a = None; a.insert(1); | |
pub fn insert(&mut self, value: T) -> &mut T { | |
*self = Some(value); | |
unsafe { self.as_mut().unwrap_unchecked() } | |
} | |
// | |
pub fn get_or_insert(&mut self, value: T) -> &mut T { | |
self.get_or_insert_with(|| value) | |
} | |
pub fn get_or_insert_default(&mut self) -> &mut T | |
where | |
T: Default, | |
{ | |
self.get_or_insert_with(Default::default) | |
} | |
pub fn get_or_insert_with<F: FnOnce() -> T>(&mut self, f: F) -> &mut T { | |
if let None = *self { | |
*self = Some(f()); | |
} | |
match self { | |
//此处类型匹配极其特殊,详细请见后面的“对结构体引用类型`&T/&mutT`的match语法研究 | |
Some(v) => v, | |
None => unsafe { hint::unreachable_unchecked() }, | |
} | |
} | |
//mem::replace分析请参考前文,用None替换原来的变量,并用新变量返回self,同时也完成了所有权的转移 | |
pub const fn take(&mut self) -> Option<T> { | |
mem::replace(self, None) | |
} | |
//用新value替换原变量,并把原变量返回 | |
pub const fn replace(&mut self, value: T) -> Option<T> { | |
mem::replace(self, Some(value)) | |
} | |
//针对Option的zip操作 | |
pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> { | |
match (self, other) { | |
(Some(a), Some(b)) => Some((a, b)), | |
_ => None, | |
} | |
} | |
//执行一个函数 | |
pub fn zip_with<U, F, R>(self, other: Option<U>, f: F) -> Option<R> | |
where | |
F: FnOnce(T, U) -> R, | |
{ | |
//此处,顺序应该是先执行self? other?,然后再调用函数 | |
Some(f(self?, other?)) | |
} | |
} |
对结构体引用类型“&T/&mut T”的match语法研究
如下代码:
struct TestStructA {a:i32, b:i32} | |
fn main() { | |
let c = TestStructA{a:1, b:2}; | |
let d = [1,2,3]; | |
match ((&c, &d)) { | |
(&e, &f) => println!("{:?} {:?}", e, f), | |
_ => println!("match nothing"), | |
} | |
} |
以上代码编译时,会发生如下错误:
error[E0507]: cannot move out of a shared reference
--> src/main.rs:9:7
|
9 | match (&c) {
| ^^^^
10 | (&e, &d) => println!("{:?}", e),
| --
| ||
| |data moved here
| |move occurs because `e` has type `TestStructA`, which does not implement the `Copy` trait
| help: consider removing the `&`: `e`
可见,如果match 引用,那对后继的绑定是有讲究的。对引用做match,本意便是不想要转移所有权。因此,在match的分支中就不能有引发所有权移动的绑定出现。
再请参考如下代码:
struct TestStructA {a:i32,b:i32} | |
fn main() { | |
let c = TestStructA{a:1, b:2}; | |
let d = [1,2,3]; | |
match ((&c, &d)) { | |
(&TestStructA{a:ref u, b:ref w}, &[ref x, ..]) => println!("{} {} {}", *u, *w, *x), | |
_ => println!("match nothing"), | |
} | |
} |
如果不想转移所有权,那上面代码的match就应该是一个标准的写法,对结构内部的变量也需要用引用来绑定,尤其是结构内部变量如果没有实现Copy Trait,那就必须用引用,否则也会引发编译告警。
为了编码上的方便,RUST针对以上的代码,支持如下简化形式:
struct TestStructA {a:i32,b:i32} | |
fn main() { | |
let c = TestStructA{a:1, b:2}; | |
let d = [1, 2, 3]; | |
match ((&c, &d)) { | |
//对比上述代码,头部少了&,模式绑定内部少了 ref,但代码功能完全一致 | |
(TestStructA{a: u, b: w}, [x,..]) => println!("{} {} {}", *u, *w, *x), | |
_ => println!("match nothing"), | |
} | |
} |
如果不知道RUST的这个语义,很可能会对这里的类型绑定感到疑惑。
从实际的使用场景分析,对结构体引用做match,其目的就是对结构体内部的成员的引用做pattern绑定。而且如果结构体内部的成员不支持Copy,那也不可能对结构体成员做pattern绑定。所以,此语法也是在RUST的所有权定义下的一个必然的简化选择。
RUST Result类型标准库代码分析
代码路径:
%USER%.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\result.rs
Result<T,E>方法的源代码如下:
impl<T, E> Result<T, E> { | |
pub const fn is_ok(&self) -> bool { | |
matches!(*self, Ok(_)) | |
} | |
pub const fn is_err(&self) -> bool { | |
!self.is_ok() | |
} | |
//用来做包装内变量与非包装的量是否相等的判断 | |
pub fn contains<U>(&self, x: &U) -> bool | |
where | |
U: PartialEq<T>, | |
{ | |
match self { | |
Ok(y) => x == y, | |
Err(_) => false, | |
} | |
} | |
//与错误变量做相等判断 | |
pub fn contains_err<F>(&self, f: &F) -> bool | |
where | |
F: PartialEq<E>, | |
{ | |
match self { | |
Ok(_) => false, | |
Err(e) => f == e, | |
} | |
} | |
//Result转换为Option, Ok->Some, Err->None | |
pub fn ok(self) -> Option<T> { | |
match self { | |
Ok(x) => Some(x), | |
Err(_) => None, | |
} | |
} | |
//Result转换为Option, Ok->None,Err->Some | |
pub fn err(self) -> Option<E> { | |
match self { | |
Ok(_) => None, | |
Err(x) => Some(x), | |
} | |
} | |
//&Result<T,E> 转换为Result<&T, &E> | |
pub const fn as_ref(&self) -> Result<&T, &E> { | |
match *self { | |
Ok(ref x) => Ok(x), | |
Err(ref x) => Err(x), | |
} | |
} | |
//&mut Result<T,E>转换为Result<&mut T, &mut E> | |
pub const fn as_mut(&mut self) -> Result<&mut T, &mut E> { | |
match *self { | |
Ok(ref mut x) => Ok(x), | |
Err(ref mut x) => Err(x), | |
} | |
} | |
//应用于函数式编程,如果是Ok, 利用闭包直接处理Result值,返回需要的新Result类型 | |
pub fn map<U, F: FnOnce(T) -> U>(self, op: F) -> Result<U, E> { | |
match self { | |
Ok(t) => Ok(op(t)), | |
Err(e) => Err(e), | |
} | |
} | |
//如果是Ok, 利用闭包处理Result值,返回需要的类型,如果是Err返回默认值 | |
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U { | |
match self { | |
Ok(t) => f(t), | |
Err(_) => default, | |
} | |
} | |
//如果是Ok, 调用闭包处理Result,返回需要的类型, 如果是Err,调用错误闭包函数处理错误 | |
pub fn map_or_else<U, D: FnOnce(E) -> U, F: FnOnce(T) -> U>(self, default: D, f: F) -> U { | |
match self { | |
Ok(t) => f(t), | |
Err(e) => default(e), | |
} | |
} | |
//如果是Err, 调用闭包函数处理错误,返回需要的类型, Ok则返回原值 | |
pub fn map_err<F, O: FnOnce(E) -> F>(self, op: O) -> Result<T, F> { | |
match self { | |
Ok(t) => Ok(t), | |
Err(e) => Err(op(e)), | |
} | |
} | |
//Result传递,Ok则返回给定的Result类型值,否则返回原值 | |
pub fn and<U>(self, res: Result<U, E>) -> Result<U, E> { | |
match self { | |
Ok(_) => res, | |
Err(e) => Err(e), | |
} | |
} | |
//Ok 则调用闭包处理,返回需要的Result类型值, 否则返回原值 | |
pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> { | |
match self { | |
Ok(t) => op(t), | |
Err(e) => Err(e), | |
} | |
} | |
//Ok返回原值,Err返回传入的默认Result类型值 | |
pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> { | |
match self { | |
Ok(v) => Ok(v), | |
Err(_) => res, | |
} | |
} | |
//Ok返回原值,Err调用函数进行处理,返回需要的Result类型值 | |
pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> { | |
match self { | |
Ok(t) => Ok(t), | |
Err(e) => op(e), | |
} | |
} | |
//解封装,Ok返回封装内的值,Err返回默认值 | |
pub fn unwrap_or(self, default: T) -> T { | |
match self { | |
Ok(t) => t, | |
Err(_) => default, | |
} | |
} | |
//解封装, Ok返回封装内的值, Err调用处理函数处理 | |
pub fn unwrap_or_else<F: FnOnce(E) -> T>(self, op: F) -> T { | |
match self { | |
Ok(t) => t, | |
Err(e) => op(e), | |
} | |
} | |
//确认返回一定是Ok时的解封装函数 | |
pub unsafe fn unwrap_unchecked(self) -> T { | |
debug_assert!(self.is_ok()); | |
match self { | |
Ok(t) => t, | |
// SAFETY: the safety contract must be upheld by the caller. | |
Err(_) => unsafe { hint::unreachable_unchecked() }, | |
} | |
} | |
//确认返回一定是Err时调用的解封装函数 | |
pub unsafe fn unwrap_err_unchecked(self) -> E { | |
debug_assert!(self.is_err()); | |
match self { | |
// SAFETY: the safety contract must be upheld by the caller. | |
Ok(_) => unsafe { hint::unreachable_unchecked() }, | |
Err(e) => e, | |
} | |
} | |
} | |
impl<T, E: fmt::Debug> Result<T, E> { | |
//解封装,Ok解封装,Err输出参数信息并退出 | |
pub fn expect(self, msg: &str) -> T { | |
match self { | |
Ok(t) => t, | |
Err(e) => unwrap_failed(msg, &e), | |
} | |
} | |
//解封装,Ok解封装,Err输出固定信息并退出 | |
pub fn unwrap(self) -> T { | |
match self { | |
Ok(t) => t, | |
Err(e) => unwrap_failed("called `Result::unwrap()` on an `Err` value", &e), | |
} | |
} | |
} | |
impl<T: fmt::Debug, E> Result<T, E> { | |
//解封装,对于Ok输出参数指定的信息并退出,Err解封装 | |
pub fn expect_err(self, msg: &str) -> E { | |
match self { | |
Ok(t) => unwrap_failed(msg, &t), | |
Err(e) => e, | |
} | |
} | |
//解封装,对于Ok输出固定的信息并退出,Err解封装 | |
pub fn unwrap_err(self) -> E { | |
match self { | |
Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", &t), | |
Err(e) => e, | |
} | |
} | |
} | |
impl<T: Default, E> Result<T, E> { | |
//解封装,Ok解封装, Err返回T的Default值 | |
pub fn unwrap_or_default(self) -> T { | |
match self { | |
Ok(x) => x, | |
Err(_) => Default::default(), | |
} | |
} | |
} | |
impl<T, E: Into<!>> Result<T, E> { | |
//解封装,Ok解封装,Err返回Never类型 | |
pub fn into_ok(self) -> T { | |
match self { | |
Ok(x) => x, | |
Err(e) => e.into(), | |
} | |
} | |
} | |
impl<T: Into<!>, E> Result<T, E> { | |
//解封装,Err解封装, Ok返回Never类型 | |
pub fn into_err(self) -> E { | |
match self { | |
Ok(x) => x.into(), | |
Err(e) => e, | |
} | |
} | |
} | |
impl<T, E> Result<Option, E> { | |
//将Result<>转换为Option | |
pub const fn transpose(self) -> Option<Result<T, E>> { | |
match self { | |
Ok(Some(x)) => Some(Ok(x)), | |
Ok(None) => None, | |
Err(e) => Some(Err(e)), | |
} | |
} | |
} |