函数

函数定义

1
2
3
fn fun(v:i32) -> i32{
    v + 3
}

定义类型以及返回类型,同时在Rust函数是一个表达式,也就是不需要return。

方法

1
2
3
4
5
6
7
struct Pair(Box<i32>, Box<i32>);
impl Pair {
    fn destory(self) {
        let Pair(x,y) = self;
        println!("Destroying Pair({}, {})", x, y);
    }
}

闭包(也称之为lambda表达式)

1
2
3
fn function(i: i32) -> i32 { i + 1 }
let closure_annotated = |i: i32| -> i32 { i + 1 };
let one = || 1;

下面看一下指针借用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
fn main() {
    let haystack = vec![1, 2, 3];

    let contains =  move|needle| haystack.contains(needle);

    println!("{}", contains(&1));
    println!("{}", contains(&4));

    println!("There're {} elements in vec", haystack.len());
    // ^ Uncommenting above line will result in compile-time error
    // because borrow checker doesn't allow re-using variable after it
    // has been moved.

    // Removing `move` from closure's signature will cause closure
    // to borrow _haystack_ variable immutably, hence _haystack_ is still
    // available and uncommenting above line will not cause an error.
}

如果变量已经被其他变量借用,那么就无法再次使用该变量,遵循的原则就是一个变量只能允许有一个引用

FnOnce/Fn/FnMut

这三个困恼了很长时间,感谢网上的资源,现在终于理解了。

首先这三个都是traits,当闭包作为一个参数传入的时候,需要指定是什么类型,也就是是上述哪种?然后Rust编译器才能够进行检查。

  • FnOnce:参数类型是 self,所以,这种类型的闭包会获取变量的所有权,生命周期只能是当前作用域,之后就会被释放了。
  • Fn:参数类型是 &self,所以,这种类型的闭包是不可变借用,不会改变变量,也不会释放该变量。所以可以运行多次。
  • FnMut:参数类型是 &mut self,所以,这种类型的闭包是可变借用,会改变变量,但不会释放该变量。所以可以运行多次。

FnOnce

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fn apply_once<F>(f: F) where
    F: FnOnce() {
    f();
}

let x = Box::new(3);
let fun = || {
    println!("{}", x);
    mem::drop(x);
};

在这里,函数fun只能运行一次,因为运行一次之后x被释放了。其中Box为堆分配函数。

FnMut

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
fn apply_mut<F>(mut f: F) where
    F: FnMut() {
    f();
    f();
}
let mut e = "xxx".to_string();
let f = || {
    e += "xxx"
};

apply_mut(f);

这里函数f能够被运行多次,同时修改了变量的值。

Fn

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
fn apply<F>(f: F) where
    F: Fn() {
    f();
    f();
}
let f = || {
    println!("{}", "fnn")
};

apply(f);

这里的闭包是不可变借用,不会改变变量,也不会释放该变量。所以可以运行多次。

闭包作为返回参数

 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
fn create_fn() -> impl Fn() {
    let text = "Fn".to_owned();

    move || println!("This is a: {}", text)
}

fn create_fnmut() -> impl FnMut() {
    let text = "FnMut".to_owned();

    move || println!("This is a: {}", text)
}

fn create_fnonce() -> impl FnOnce() {
    let text = "FnOnce".to_owned();

    move || println!("This is a: {}", text)
}

fn main() {
    let fn_plain = create_fn();
    let mut fn_mut = create_fnmut();
    let fn_once = create_fnonce();

    fn_plain();
    fn_mut();
    fn_once();
}

标准库中的闭包

 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
let array1 = [1, 2, 3];
println!("2 in array1: {}", array1.iter().any(|&x| x == 2));

println!("Find 2 in array1: {:?}", array1.iter().find(|&&x| x == 2));

let upper = 12;
let sum_of_squared_odd_numbers: u32 =
    (0..)
        .map(|n| n * n)
        .take_while(|&n_squared| n_squared < upper)
        .filter(|&n_squared| is_odd(n_squared))
        .fold(0, |acc, n_squared| acc + n_squared);

//高阶函数的用法
fn main() {
    let mut acc = 0;
    for i in 0..=3 {
        let a :u32 = match i % 2 ==1 {
            true => i,
            false => continue,
        };
        acc += a;
    }

    println!("{}", acc);
}

参考