当前位置:网站首页>Correct opening method of option
Correct opening method of option
2022-04-23 18:04:00 【Xu Yeping】
Option The right way to open
1. What?
Suppose you have Rust elements of grammar , Just to recap ,Option Is an enumerated type , It grows like this. :
pub enum Option<T> {
None,
Some(T),
}
Its location :std::option::Option
2. Use scenarios
according to std::option Introduction to ,Option There are the following 7 Usage .
- initialize value
- As the return value of a function not defined in the whole input range
- If the function may have errors , You can use
Option<T>
As return value , useNone
Represents possible errors . - Used as a
struct
Optional fields for - Used as an optional argument to a function
- Null pointer
- Used as a return value for complex situations
2.1 initialize value
If a variable may have a value , Or maybe not , Then you can use Option<T>
Initialize the variable .
let s = Some(3);
if let Some(ref s) = s{
println!("{:?}",*s);
}
The effect of having or not having a value , Only when this variable is used , Otherwise it's just println!()
There is no need to initialize a Option
, Can use one Option<T>
There are several kinds of situations , Namely :
- Return value as function
struct
WithOption<T>
The field of , To initialize this field, you need to createOption<T>
- As a function parameter
Through one set_score()
by struct Student
Set the value
#[derive(Debug)]
struct Student {
name:String,
year:u8,
score:Option<f32>// Optional fields
}
impl Student{
fn new(n:String,y:u8)->Self{
Self{
name:n,
year:y,
score:None,
}
}
// receive Option As a parameter
fn set_score(&mut self,s:Option<f32>){
self.score = s;
}
}
// return Option
fn compute_score(s:f32)->Option<f32>{
let d = s*0.75;
Some(d)
}
fn main(){
let mut d = Student::new("xiaoming".to_string(),18);
dbg!(&d.score);
let score = compute_score(100.0);
d.set_score(score);
dbg!(&d.score);
}
[Running: cargo run --message-format=json]
Compiling study v0.1.0 (/home/banapy/projects/study)
Finished dev [unoptimized + debuginfo] target(s) in 0.65s
Running `target/debug/study`
[src/main.rs:25] &d.score = None
[src/main.rs:28] &d.score = Some(
75.0
)
[Finished in 0.8s]
2.2 Null pointer
Here is an example of moving a standard library
Rust The pointer to must be a valid memory address , therefore Rust There is no null pointer , Instead, an optional pointer (optional pointer), such as Option<Box<T>>
.
The chestnuts below use Option Create a Option<Box<i32>>
, In order to use i32
Value ,check_option
The function uses pattern matching , Judge box
Whether there is value in , because Option
It may not be worth it .
let optional = None;
check_optional(optional);
let optional = Some(Box::new(9000));
check_optional(optional);
// receive Option As a parameter
fn check_optional(optional: Option<Box<i32>>) {
match optional {
Some(ref p) => println!("has value {}", p),
None => println!("has no value"),
}
}
The example above uses Option Create a safe nullable pointer (nullable pointer), such Option The usage of is in Rust Very common in , therefore Rust This has been optimized , Make sure Option<Box> As efficient as a very ordinary pointer , Without extra cost .
2.3 Return value of complex case
Rust It's a statically strongly typed language , characteristic trait Is that the compilation period adopts the static distribution method for each struct
Add method , therefore Rust There is no additional overhead in the abstraction of .
When we call a complex library , Implement a with a type placeholder trait when , We need to specify a type , Otherwise, it cannot be compiled , But this type is not arbitrarily specified , It may need to implement some kind of trait, Because some kind of... May be used in subsequent operations trait Methods , At this time, the library will provide us with some implementation trait The type of Foundation , such as Option<T>
,Result<T,E>
etc. .
Look at actix An example of :
Don't know what is actix,actix chinese
actix file ,actixDoc
Create a Actor You need to implement... For its structure trait Actor
.
extern crate actix;
use actix::prelude::*;
struct MyActor;
impl Actor for MyActor {
type Context = Context<Self>;
}
Actor Communicate with each other through messages , When Actor After receiving a message , We're going to define a handle Handle this message .
struct WhoAmI;
impl Message for WhoAmI {
// Specified here as Option<Addr<MyActor>> type
type Result = Option<actix::Addr<MyActor>, ()>;
}
impl Handler<WhoAmI> for MyActor {
type Result = Option<actix::Addr<MyActor>, ()>;
fn handle(&mut self, msg: WhoAmI, ctx: &mut Context<Self>) -> Self::Result {
Ok(ctx.address())
}
}
Message processing has a result , because Rust Static strong type of , We must specify a data type for the result type Result=Option<T>
, This data type is not arbitrarily specified , It needs to be realized. trait MessageResponse
, But we are too lazy , Don't want to take the time to achieve this trait, It can't be realized , You can use actix The base type provided by the library , These types all implement MessageResponse
, such as Option<T>
, At this time ,Option<T>
You can bring out the value to be returned in this complex case .
Of course, there are more complicated situations , Welcome to summarize .
after one's words Option Several usage scenarios of , Let's take a look at Option Available actions .
3 Available actions
- match
- if let
- unwrap() Wait for the combiner
match It's a powerful pattern matching , Very suitable for matching Option And so on .
fn main(){
let d = Student::new("xiaoming".to_string(),18);
let d = Some(d);
match d{
Some(s)=>{
println!("{:?}", s.name);
}
None=>{
println!("None");
}
}
}
match Easy to operate , It's just a little lengthy , as everyone knows , Programmers are quite “ lazy ”, Don't want to write a little extra code , In many cases, we don't care what the error value is , Just want to use Option In the value of the , Then a simple if let Sentences save us a lot of things .
fn main(){
let d = Student::new("xiaoming".to_string(),18);
let d = Some(&d);
let num = if let Some(s) = d{
println!("{:?}", s.name);
Some(3)
}
}
Option Some basic operations , I believe you can understand it as soon as you read it , No more details here , Let's focus on Option The combiner . This kind of writing belongs to functional programming , The new contact must be right map
, map_or
,map_or_else
Confused .
The so-called functional expression is a programming paradigm ,Rust Functional programming support , Do not represent Rust It's a functional programming language .
Want to know about functional programming ?
Functional programming – Baidu Encyclopedia
Let's explain , Source code , The order of the examples , Introduce these interesting things one by one :
Be careful : Assertion assert_eq!(a,b), If a==b, Nothing happened , Otherwise interrupt the program .
3.1. expect()
-
explain :
Valuable , Return value , otherwise , Interrupt the program , Print msg error message . -
Source code :
pub fn expect(self, msg: &str) -> T {
match self {
Some(val) => val,
None => expect_failed(msg),
}
}
- chestnuts :
let x = Some("value");
assert_eq!(x.expect("the world is ending"), "value");
let x: Option<&str> = None;
x.expect("the world is ending"); // panics with `the world is ending`
3.2. unwrap()
-
explain :
Valuable , Return value , otherwise , Interrupt the program . -
Source code :
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
None => panic!("called `Option::unwrap()` on a `None` value"),
}
}
- chestnuts :
let x = Some("air");
assert_eq!(x.unwrap(), "air");
let x: Option<&str> = None;
assert_eq!(x.unwrap(), "air"); // fails
3.3. unwrap_or()
- explain :
Valuable , Return value , Otherwise, return a default value . - Source code :
pub fn unwrap_or(self, def: T) -> T {
match self {
Some(x) => x,
None => def,
}
}
- chestnuts :
assert_eq!(Some("car").unwrap_or("bike"), "car");
assert_eq!(None.unwrap_or("bike"), "bike");
3.4. unwrap_or_else()
- explain :
Valuable , Return value , otherwise , Execute closure . - Source code :
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
match self {
Some(x) => x,
None => f(),
}
}
chestnuts :
let k = 10;
assert_eq!(Some(4).unwrap_or_else(|| 2 * k), 4);
assert_eq!(None.unwrap_or_else(|| 2 * k), 20);
3.5. map()
- explain :
Change the value , And back to another Option. - Source code :
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
match self {
Some(x) => Some(f(x)),
None => None,
}
}
- chestnuts :
let maybe_some_string = Some(String::from("Hello, World!"));
// `Option::map` takes self *by value*, consuming `maybe_some_string`
let maybe_some_len = maybe_some_string.map(|s| s.len());
assert_eq!(maybe_some_len, Some(13));
3.6. map_or()
- explain :
Valuable , Then execute the closure and return the value , Otherwise, a custom default value is returned . - Source code :
pub fn map_or<U, F: FnOnce(T) -> U>(self, default: U, f: F) -> U {
match self {
Some(t) => f(t),
None => default,
}
}
- chestnuts :
let x = Some("foo");
assert_eq!(x.map_or(42, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or(42, |v| v.len()), 42);
3.7. map_or_else()
- explain :
Valuable , Execute closure , Otherwise, execute another closure . - Source code :
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(),
}
}
- chestnuts :
let k = 21;
let x = Some("foo");
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 3);
let x: Option<&str> = None;
assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42);
3.8. ok_or()
- explain :
Valuable , return Result, Otherwise, a custom error will be returned . - Source code :
pub fn ok_or<E>(self, err: E) -> Result<T, E> {
match self {
Some(v) => Ok(v),
None => Err(err),
}
}
- chestnuts :
let x = Some("foo");
assert_eq!(x.ok_or(0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or(0), Err(0));
3.9. ok_or_else()
- explain :
Valuable , return Result, Otherwise, execute the closure representing the error . - Source code :
pub fn ok_or_else<E, F: FnOnce() -> E>(self, err: F) -> Result<T, E> {
match self {
Some(v) => Ok(v),
None => Err(err()),
}
}
- chestnuts :
let x = Some("foo");
assert_eq!(x.ok_or_else(|| 0), Ok("foo"));
let x: Option<&str> = None;
assert_eq!(x.ok_or_else(|| 0), Err(0));
3.10. iter()
- explain :
hold Option Convert to iterator . - Source code :
pub fn iter(&self) -> Iter<T> {
Iter {
inner: Item {
opt: self.as_ref() } }
}
- chestnuts :
let x = Some(4);
assert_eq!(x.iter().next(), Some(&4));
let x: Option<u32> = None;
assert_eq!(x.iter().next(), None);
3.11. and()
- explain :
Valuable , Return to another Option, Otherwise return to None. - Source code :
pub fn and<U>(self, optb: Option<U>) -> Option<U> {
match self {
Some(_) => optb,
None => None,
}
}
- chestnuts :
let x = Some(2);
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
let x: Option<u32> = None;
let y = Some("foo");
assert_eq!(x.and(y), None);
let x = Some(2);
let y = Some("foo");
assert_eq!(x.and(y), Some("foo"));
let x: Option<u32> = None;
let y: Option<&str> = None;
assert_eq!(x.and(y), None);
3.12. and_then()
- explain :
Valuable , Execute closure , Otherwise return to None. - Source code :
pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
match self {
Some(x) => f(x),
None => None,
}
}
- chestnuts :
fn sq(x: u32) -> Option<u32> {
Some(x * x) }
fn nope(_: u32) -> Option<u32> {
None }
assert_eq!(Some(2).and_then(sq).and_then(sq), Some(16));
assert_eq!(Some(2).and_then(sq).and_then(nope), None);
assert_eq!(Some(2).and_then(nope).and_then(sq), None);
assert_eq!(None.and_then(sq).and_then(sq), None);
3.13 filter()
- explain :
filter , Filter out the value you want . - Source code :
pub fn filter<P: FnOnce(&T) -> bool>(self, predicate: P) -> Self {
if let Some(x) = self {
if predicate(&x) {
return Some(x)
}
}
None
}
chestnuts :
fn is_even(n: &i32) -> bool {
n % 2 == 0
}
assert_eq!(None.filter(is_even), None);
assert_eq!(Some(3).filter(is_even), None);
assert_eq!(Some(4).filter(is_even), Some(4));
3.14 or()
- explain :
Valuable , Return to oneself , Otherwise return to custom Option. - Source code :
pub fn or(self, optb: Option<T>) -> Option<T> {
match self {
Some(_) => self,
None => optb,
}
}
chestnuts :
let x = Some(2);
let y = None;
assert_eq!(x.or(y), Some(2));
let x = None;
let y = Some(100);
assert_eq!(x.or(y), Some(100));
let x = Some(2);
let y = Some(100);
assert_eq!(x.or(y), Some(2));
let x: Option<u32> = None;
let y = None;
assert_eq!(x.or(y), None);
3.15 or_else()
- explain :
Valuable , Return to oneself , Otherwise, execute the closure . - Source code :
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
match self {
Some(_) => self,
None => f(),
}
}
- chestnuts :
fn nobody() -> Option<&'static str> {
None }
fn vikings() -> Option<&'static str> {
Some("vikings") }
assert_eq!(Some("barbarians").or_else(vikings), Some("barbarians"));
assert_eq!(None.or_else(vikings), Some("vikings"));
assert_eq!(None.or_else(nobody), None);
3.16 take()
- explain :
Take out a value . - Source code :
pub fn take(&mut self) -> Option<T> {
mem::replace(self, None)
}
- chestnuts :
let mut x = Some(2);
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, Some(2));
let mut x: Option<u32> = None;
let y = x.take();
assert_eq!(x, None);
assert_eq!(y, None);
Welcome to correct !
author :Nuko
link :https://www.jianshu.com/p/ce5bddf4b335
source : Simple books
The copyright belongs to the author . Commercial reprint please contact the author for authorization , Non-commercial reprint please indicate the source .
版权声明
本文为[Xu Yeping]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204230544498339.html
边栏推荐
猜你喜欢
Docker 安装 Redis
Calculation of fishing net road density
Process management command
String function in MySQL
Summary of floating point double precision, single precision and half precision knowledge
mysql自动启动设置用Systemctl start mysqld启动
Nat commun | current progress and open challenges of applied deep learning in Bioscience
Eigen learning summary
Logic regression principle and code implementation
Go对文件操作
随机推荐
ArcGIS license error -15 solution
Go language JSON package usage
[UDS unified diagnostic service] IV. typical diagnostic service (4) - online programming function unit (0x34-0x38)
cv_ Solution of mismatch between bridge and opencv
The ultimate experience, the audio and video technology behind the tiktok
Qt读写XML文件(含源码+注释)
Gaode map search, drag and drop query address
2022江西光伏展,中國分布式光伏展會,南昌太陽能利用展
Solving the problem of displaying too many unique values in ArcGIS partition statistics failed
Batch export ArcGIS attribute table
MySQL_01_简单数据检索
Open source key component multi_ Button use, including test engineering
Generate verification code
YOLOv4剪枝【附代码】
Go对文件操作
Utilisation de la liste - Ajouter, supprimer et modifier la requête
Docker 安装 MySQL
What are the relationships and differences between threads and processes
undefined reference to `Nabo::NearestNeighbourSearch
mysql自动启动设置用Systemctl start mysqld启动