A collection of the knowledge of Rust programming: Rust programming, Option learning

Keywords: github

Video address

Headline address: https://www.ixigua.com/i6765442674582356483
Address of station B: https://www.bilibili.com/video/av7806209? P = 1
Netease cloud classroom address: https://study.163.com/course/introduction.htm? Courseid = 1209596906 yuan / coursedetail? Tab = 1

github address

github address

introduce

The option type represents an optional value. Each option is either a value in a certain or a None. Option is defined as follows:

pub enum Option<T> {
    None,
    Some(T),
}

usage

Option s are mainly used in the following ways:

  • Initialization value;

  • As the return value of a function not defined in the entire input range;

  • As the return value, use None to indicate the simple error;

  • As an optional field of the structure;

  • As a loanable or loadable field in the structure;

  • As optional parameter of function;

  • Represents a null pointer;

  • Used as a return value for complex situations.

Here, we give an example of "fields that can be lent or loaded as structures".

use std::thread;
use std::time::Duration;

struct Worker {
    thread: thread::JoinHandle<()>,
}

impl Worker {
    fn new() -> Worker {
        let thread = thread::spawn(move || {
            println!("start sleep 10 secs ...");
            thread::sleep(Duration::from_secs(10));
        });
        Worker {
            thread: thread,
        }
    }
}

struct ThreadPool {
    workers: Vec<Worker>,
}

impl ThreadPool {
    fn new(size: usize) -> ThreadPool {
        assert!(size > 0);
        let mut workers = Vec::with_capacity(size);
        for _ in 0..size {
            workers.push(Worker::new());
        }

        ThreadPool { workers }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for worker in &mut self.workers {
            worker.thread.join().unwrap();//Error reporting, unable to compile, and thread unable to implement copy trace
            println!("worker thread finished!");
        }
    }
}

fn main() {
    let _pool = ThreadPool::new(3);
    println!("Hello, world!");
}

In the above example, an incomplete thread pool is implemented. In worker, a field is the handle of thread. When the thread pool object drop s, you cannot use the reference of the member in the MUT object (that is, take out the worker through & mut self. Workers, and call worker.thread.join()). To solve this problem, we can modify the worker structure as follows:

struct Worker {
    // thread: thread::JoinHandle<()>,
    thread: Option<thread::JoinHandle<()>>,
}

The complete code is:

use std::thread;
use std::time::Duration;

struct Worker {
    // thread: thread::JoinHandle<()>,
    thread: Option<thread::JoinHandle<()>>,
}

impl Worker {
    fn new() -> Worker {
        let thread = thread::spawn(move || {
            println!("start sleep 10 secs ...");
            thread::sleep(Duration::from_secs(10));
        });
        Worker {
            // thread: thread,
            thread: Some(thread),
        }
    }
}

struct ThreadPool {
    workers: Vec<Worker>,
}

impl ThreadPool {
    fn new(size: usize) -> ThreadPool {
        assert!(size > 0);
        let mut workers = Vec::with_capacity(size);
        for _ in 0..size {
            workers.push(Worker::new());
        }

        ThreadPool { workers }
    }
}

impl Drop for ThreadPool {
    fn drop(&mut self) {
        for worker in &mut self.workers {
            // worker.thread.join().unwrap();
            // println!("worker thread finished!");
            
            if let Some(thread) = worker.thread.take() {//Here, take the thread out of the Option of the thread field of the Worker, and use "Option type as the loanable or loadable field in the structure"
                thread.join().unwrap();
                println!("worker thread finished!");
            }
        }
    }
}

fn main() {
    let _pool = ThreadPool::new(3);
    println!("Hello, world!");
}

In the drop implementation of ThreadPool, the thread is removed from worker through the take method of option, and then join is invoked to solve the problem successfully.

Method

  • is_some

    pub fn is_some(&self) -> bool
    

    Returns true when there is a value in Option.

  • is_none

    pub fn is_none(&self) -> bool
    

    Returns true when Option is None.

  • contains

    pub fn contains<U>(&self, x: &U) -> bool
    where
        U: PartialEq<T>, 
    

    Returns true when the given value is included in Some. This is the nightly API.

    //Example
    #![feature(option_result_contains)]
    
    let x: Option<u32> = Some(2);
    assert_eq!(x.contains(&2), true);
    
    let x: Option<u32> = Some(3);
    assert_eq!(x.contains(&2), false);
    
  • as_ref

    pub fn as_ref(&self) -> Option<&T>
    

    Convert & option < T > to option < & T >

    //Example
    let text: Option<String> = Some("Hello, world!".to_string());
    
    let text_length: Option<usize> = text.as_ref().map(|s| s.len());
    println!("still can print text: {:?}", text);
    
  • take

    pub fn take(&mut self) -> Option<T>
    

    Take the value out of Option and leave None.

    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);
    
  • copied

    pub fn copied(self) -> Option<T>
    

    Get option < T > from option < & T > (by copying)

    let x = 12;
    
    let opt_x = Some(&x);
    assert_eq!(opt_x, Some(&12));
    
    let copied = opt_x.copied();
    assert_eq!(copied, Some(12));
    
  • cloned

    pub fn cloned(self) -> Option<T>
    

    Get option < T > from option < & T > (by cloning)

    let x = 12;
    
    let opt_x = Some(&x);
    assert_eq!(opt_x, Some(&12));
    
    let cloned = opt_x.cloned();
    assert_eq!(cloned, Some(12));
    
143 original articles published· Praised 286· 40000 visitors+
Private letter follow

Posted by dprichard on Fri, 10 Apr 2020 00:16:04 -0700