标准库

这一章主要介绍标准库,Rust中提供了各种各样的标准库供我们使用。

  • String
  • vectors
  • Option
  • Result
  • Box

Box

Box是一个智能指针,在计算机程序中,所有的值都是在栈中分配的,同时是固定大小的。但是可以使用Box来向堆中分配空间,同时返回一个指针,如果指针不在上下文中,那么分配的区域就会被回收。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
use std::mem;

struct Point {
    x: f64,
    y: f64,
}

fn origin() -> Point {
    Point { x: 0., y: 0. }
}

fn main() {
    let point: Point = origin();
    // 栈
    println!("Point occupies {} bytes on the stack",
             mem::size_of_val(&point));

    let boxed_point: Box<Point> = Box::new(origin());
    //堆
    println!("Boxed point occupies {} bytes on the stack",
             mem::size_of_val(&boxed_point));
}

Result

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
mod checked {
    // Mathematical "errors" we want to catch
    #[derive(Debug)]
    pub enum MathError {
        DivisionByZero,
        NonPositiveLogarithm,
        NegativeSquareRoot,
    }

    pub type MathResult = Result<f64, MathError>;

    pub fn div(x: f64, y: f64) -> MathResult {
        if y == 0.0 {
            // This operation would `fail`, instead let's return the reason of
            // the failure wrapped in `Err`
            Err(MathError::DivisionByZero)
        } else {
            // This operation is valid, return the result wrapped in `Ok`
            Ok(x / y)
        }
    }

    pub fn sqrt(x: f64) -> MathResult {
        if x < 0.0 {
            Err(MathError::NegativeSquareRoot)
        } else {
            Ok(x.sqrt())
        }
    }

    pub fn ln(x: f64) -> MathResult {
        if x <= 0.0 {
            Err(MathError::NonPositiveLogarithm)
        } else {
            Ok(x.ln())
        }
    }
}

// `op(x, y)` === `sqrt(ln(x / y))`
fn op(x: f64, y: f64) -> f64 {
    // This is a three level match pyramid!
    match checked::div(x, y) {
        Err(why) => panic!("{:?}", why),
        Ok(ratio) => match checked::ln(ratio) {
            Err(why) => panic!("{:?}", why),
            Ok(ln) => match checked::sqrt(ln) {
                Err(why) => panic!("{:?}", why),
                Ok(sqrt) => sqrt,
            },
        },
    }
}

fn main() {
    // Will this fail?
    println!("{}", op(1.0, 10.0));
}

HashMap

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
fn main() { 
    let mut contacts = HashMap::new();

    contacts.insert("Daniel", "798-1364");
    contacts.insert("Ashley", "645-7689");
    contacts.insert("Katie", "435-8291");
    contacts.insert("Robert", "956-1745");

    // Takes a reference and returns Option<&V>
    match contacts.get(&"Daniel") {
        Some(&number) => println!("Calling Daniel: {}", call(number)),
        _ => println!("Don't have Daniel's number."),
    }

    // `HashMap::insert()` returns `None`
    // if the inserted value is new, `Some(value)` otherwise
    contacts.insert("Daniel", "164-6743");

    match contacts.get(&"Ashley") {
        Some(&number) => println!("Calling Ashley: {}", call(number)),
        _ => println!("Don't have Ashley's number."),
    }

    contacts.remove(&"Ashley"); 

    // `HashMap::iter()` returns an iterator that yields 
    // (&'a key, &'a value) pairs in arbitrary order.
    for (contact, &number) in contacts.iter() {
        println!("Calling {}: {}", contact, call(number)); 
    }
}

Rc

当需要多个所有着的时候,Rc(Reference Counting)是非常有用的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
use std::rc::Rc;

fn main() {
    let rc_examples = "Rc examples".to_string();
    {
        let rc_a: Rc<String> = Rc::new(rc_examples);
        println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));
        {
            let rc_b: Rc<String> = Rc::clone(&rc_a);
            println!("Reference Count of rc_b: {}", Rc::strong_count(&rc_b));
            println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));
        }

        println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a));

    }
    // error
    println!("rc_examples: {}", rc_examples);
}

misc(多线程)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
use std::thread;
static NTHREADS: i32 = 100;
fn main() {
    let mut children = vec![];
    for i in 0..NTHREADS {
        // 将i move到闭包中
        children.push(thread::spawn(  move||{
            println!("this is thread number {}", i);
        }));
    }

    for child in children {
        let _ = child.join();
    }
}

MapReduce

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use std::thread;


fn main() {
    let data = "86967897737416471853297327050364959
11861322575564723963297542624962850
70856234701860851907960690014725639
38397966707106094172783238747669219
52380795257888236525459303330302837
58495327135744041048897885734297812
69920216438980873548808413720956532
16278424637452589860345374828574669";

    let mut children = vec![];

    let chunked_data = data.split_whitespace();

    for (i, data_segment) in chunked_data.enumerate() {
        children.push(thread::spawn(move || -> u32{
            let result = data_segment
                .chars()
                .map(|c| c.to_digit(10).expect("should be digital"))
                .sum();

            result
        }));
    }

    let mut intermediate_sums = vec![];

    for child in children {
        let intermediate_sum = child.join().unwrap();
        intermediate_sums.push(intermediate_sum);
    }
    let final_result = intermediate_sums.iter().sum::<u32>();
    println!("Final sum result: {}", final_result);

}

channel(管道)

Rust提供了channel使得进程之间相互通信。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use std::thread;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;


static THREAD: i32 = 10000;

fn main() {
    //定义一个channel
    let (tx, rx): (Sender<i32>, Receiver<i32>) = mpsc::channel();

    let mut children = Vec::new();

    for id in 0..THREAD {
        let thread_tx = tx.clone();

        let child = thread::spawn(move || {
            // 将处理的结果放到管道中
            let r = id * 100;

            thread_tx.send(r).unwrap();
        });

        children.push(child);
    }

    let mut ids = Vec::with_capacity(THREAD as usize);

    for _ in 0..THREAD {
        ids.push(rx.recv().unwrap());
    }

    for c in children {
        c.join().unwrap();
    }

    println!("{:?}", ids);
}

ARC

是一个Atomic的只能指针

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let v = Arc::new(Mutex::new(vec![1,2,3]));

    for i in 0..3 {
        //将v拷贝进来
      let cloned_v = v.clone();
      thread::spawn(move || {
         cloned_v.lock().unwrap().push(i);
      });
    }
}

FFI

FFI全称为Foreign Function Interface,能够调用其他语言编写的函数,只需要进行声明就行了。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
use std::fmt;

#[link(name = "m")]
extern {
    // this is a foreign function
    // that computes the square root of a single precision complex number
    fn csqrtf(z: Complex) -> Complex;

    fn ccosf(z: Complex) -> Complex;
}

#[repr(C)]
#[derive(Clone, Copy)]
struct Complex {
    re: f32,
    im: f32,
}

impl fmt::Debug for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}

fn main() {
    let z = Complex { re: -1., im: 0. };
    let z_sqrt = unsafe { csqrtf(z) };

    println!("the square root of {:?} is {:?}", z, z_sqrt);
}

参考