Option 表示值,如果有值则Some包装其值,否则返回None。
fn divide(a: f32, b: f32) -> Option<f32> {
if b == 0.0f32 {
None
} else {
Some(a / b)
}
}
fn main() {
let a = 1.0f32;
let b = 2.0f32;
let c = 0.0f32;
let r = divide(a, b);
println!("r = {:?}", r);
println!("divide zero = {:?}", divide(a, c));
}
rust指针必须指向可用的位置,不是为null引用。比较之下,Rust有一个Option指针,类似于Option<Box
fn check_optional(optional: Option<Box<i32>>) {
match optional {
Some(p) => {
println!("解引用里面的值:{p}");
}
None => {
println! {"Optional为空"};
}
}
}
fn main() {
let optional1 = None;
check_optional(optional1);
let optional2 = Some(Box::new(99));
check_optional(optional2);
}
Option的简化操作,如果我们要对向量中最后两个元素求和:
fn add_last_numbers(s: &mut Vec<i32>) -> Option<i32> {
let a = s.pop();
let b = s.pop();
match (a, b) {
(Some(x), Some(y)) => Some(x + y),
_ => None,
}
}
fn main() {
let mut a = vec![1, 2, 3, 4];
let b = add_last_numbers(&mut a);
println!("b = {:?}", b);
}
我们也可以:
fn add_last_numbers(s: &mut Vec<i32>) -> Option<i32> {
Some(s.pop()? + s.pop()?)
}
这里的?
表达式将对Some
解包,如果是None则结果还是None。这样就不用对Option的值层层匹配避免冗余操作。
Option常用方法
as_ref
:将&Option<T>
转换为Option<&T>
。as_mut
:转换&mut Option为Option<&mut T>。 as_deref
:转换&Option为Option<&T::Target>。 as_deref_mut
:转换&mut Option<T>
为Option<&mut T::Target>
。as_pin_ref
:转换Pin<&Option<T>
为Option<Pin<&T>
。as_pin_ref
:转换Pin<&Option<T>>
为Option<Pin<&T>>
。as_pin_mut
:转换Pin<&mut Option<T>>
为Option<Pin<&mut T>>
。expect
:如果为None则爆出给定的错误信息。unwrap
:如果为None则爆出错误信息否则解包Option里面的元素。unwrap_or
:如果为None则返回给定的值,否则解包。unwrap_or_default
:返回类型T
的默认值。unwrap_or_else
:返回提供的值。是ok_or
:转换Some(b)
为Ok(b)
,None
为Err(err)
。ok_or_else
:转换Some(v)
为Ok(v)
、None
为Err
的值。transpose
:转换Option
的结果为Result。filter
:对Some(t)的t调用函数,如果为Option包含值则函数返回True,否则返回None。map
:使用提供的函数转换Option为Option,如果Option为Some则映射转换否则返回None。 map_or
:如果Option是Some则返回Some的值,否则返回默认值。map_or_else
:如果是Some则使用函数,否则返回callback函数的调用结果。zip
:如果self是Some(s)
提供了Option(o)
返回Some((s,o))
,否则返回None。zip_with
:调用提供的函数,如果Option是Some(o)
提供的Some(s)
则返回Some(f(s,o))
,否则返回None。
逻辑运算:
方法 | self(Option本身) | 运算输入 | 运算输出 |
---|---|---|---|
and | None | ignore(表示无论是什么输出都一样) | None |
and | Some(x) | None | None |
and | Some(x) | Some(y) | Some(y) |
or | None | None | None |
or | None | Some(y) | Some(y) |
or | Some(x) | ignore | Some(x) |
xor | None | None | None |
xor | None | Some(y) | Some(y) |
xor | Some(x) | None | Some(x) |
xor | Some(x) | Some(y) | None |
and_then和or_else方法接受函数输入,当有值的时候产生一个新的值,and_then方法生成一个Option不同于原来的Option
方法 | self | function输入 | function result | 输出 |
---|---|---|---|---|
and_then | None | 无输入 | 无计算 | None |
and_then | Some(x) | x | None | None |
and_then | Some(x) | x | Some(y) | Some(y) |
or_else | None | 无输入 | None | None |
or_else | None | 无输入 | Some(y) | Some(y) |
or_else | Some(x) | 无输入 | 无计算 | Some(x) |
and_then或者是or_else常用在pipeline调用的场景,pipeline中的一个状态计算失败则传递None,否则继续处理Some里面的值。
比较运算符:
如果T本身实现了PartialOrd然后Option
assert!(None < Some(0));
assert!(Some(0) < Some(1));
在Option上迭代:
- into_iter:消耗Option,生成其中包含的值。
- iter:生成一个无法修改的&T的值。
- iter_mut:生成一个可变值的引用。
main() {
let yep = Some(4);
let nope = None;
//chain方法调用into_iter生成迭代器,这里yep为Some(4)则将4取出
let nums: Vec<i32> = (0..4).chain(yep).chain(4..8).collect();
assert_eq!(nums, [0, 1, 2, 3, 4, 4, 5, 6, 7]);
//chain方法调用into_iter生成迭代器,这里Nope为None则无法取出。
let nums1: Vec<i32> = (0..4).chain(nope).chain(4..8).collect();
assert_eq!(nums1, [0, 1, 2, 3, 4, 5, 6, 7]);
}
Option 实现了FromIterator trait:可以在Option的值上收集值进一个Option集合,如果Option本身有任何一个元素为None则结果为None。
fn main() {
let v = [Some(2), Some(4), None, Some(8)];
let res: Option<Vec<_>> = v.into_iter().collect();//包含一个None
assert_eq!(res, None);
let v = [Some(2), Some(4), Some(8)];
let res: Option<Vec<_>> = v.into_iter().collect();
assert_eq!(res, Some(vec![2, 4, 8]));
}
Option也实现了Product和Sumt rait,允许Option里面的元素累积和累和。
fn main(){
let v = [None, Some(1), Some(2), Some(3)];
let res: Option<i32> = v.into_iter().sum();//包含有None,求和为None
assert_eq!(res, None);
let v = [Some(1), Some(2), Some(21)];
let res: Option<i32> = v.into_iter().product();
assert_eq!(res, Some(42));
}
原位修改Option:
- insert:插入一个值,删除老值。
- get_or_insert:获取当前值,如果为None则插入提供的值。
- get_or_insert_default:获取当前值,插入T类型的默认值(必须实现Default)。
- get_or_insert_with:获取当前值插入,如果为None则默认函数计算值。
转换Option值的所有权: - take:获取Option的值得所有权,如果Option为None的使用None替代。
- replace:获取Option值的所有权,如果有任何元素,使用Some(value)替代。
let msg = Some("howdy");
// Take a reference to the contained string
if let Some(m) = &msg {
println!("{}", *m);
}
// Remove the contained string, destroying the Option
let unwrapped_msg = msg.unwrap_or("default message");
循环之前初始化结果为None:
enum Kingdom { Plant(u32, &'static str), Animal(u32, &'static str) }
// A list of data to search through.
let all_the_big_things = [
Kingdom::Plant(250, "redwood"),
Kingdom::Plant(230, "noble fir"),
Kingdom::Plant(229, "sugar pine"),
Kingdom::Animal(25, "blue whale"),
Kingdom::Animal(19, "fin whale"),
Kingdom::Animal(15, "north pacific right whale"),
];
// We're going to search for the name of the biggest animal,
// but to start with we've just got `None`.
let mut name_of_biggest_animal = None;
let mut size_of_biggest_animal = 0;
for big_thing in &all_the_big_things {
match *big_thing {
Kingdom::Animal(size, name) if size > size_of_biggest_animal => {
// Now we've found the name of some big animal
size_of_biggest_animal = size;
name_of_biggest_animal = Some(name);
}
Kingdom::Animal(..) | Kingdom::Plant(..) => ()
}
}
match name_of_biggest_animal {
Some(name) => println!("the biggest animal is {name}"),
None => println!("there are no animals :("),
}
is_some
:判断Option是否为Some。