rust 函数 和 闭包 -10

目录

 

一,函数

(一)函数的声明格式

(二)用函数实现两数交换值

二,闭包

(一)闭包的声明格式

    (二)使用闭包实现两数交换值

三,异同

(一)作用域不同

(二)三个特性(所有权,可变借用和不可变借用)一致

1,所有权

2,借用

3,可变借用


一,函数

(一)函数的声明格式


              &mut修饰符在变量名前,函数定义时形式参数必须声明类型,这是出于安全的考虑,这样就不需要再进行推断了。

 fn fn_name( 变量名 :[&mut] 变量类型 [,...]) -> 返回类型{ 
   // code_block 
    [返回参数]
}

 fn fn_name( 变量名 :[&mut] 变量类型 [,...]) { 
   // code_block 
   return 返回参数; 
}


(二)用函数实现两数交换值

fn main() {
    let  mut num1 = 1;
    let  mut num2 = 2;
    println!("num1:{} , num2:{}", num1,num2);
    
    //第一次交换
    let  array = chang_num(num1  , num2);
    num1 = {
         array[0]
    };
    num2 =  array[1] ;
    println!("num1:{} , num2:{}", num1,num2);

    //第二次交换
    num1 = {
        let mut temp = num2;
        num2 = num1;
        temp
    };
    println!("num1:{} , num2:{}", num1,num2);
}

fn chang_num(num1 : i32  , num2:i32) ->[i32;2]{
    return  [num2,num1];
}

二,闭包

(一)闭包的声明格式

       一个可以储存在变量里的类似函数的结构。闭包通常很短并只与对应相对任意的场景较小的上下文中。编译器能可靠的推断参数和返回值的类型,类似于它是如何能够推断大部分变量的类型一样。
相同的闭包在相同的上下文内,不允许有不同的参数类型。类型是在第一次传参数时确定的。

//函数定义
fn fn1(x: u32) -> u32 {
    x + 1
}

fn main() {
    //这俩都是有效的闭包定义,并在调用时产生相同的行为。
    let closures1 = |x: u32| -> u32 { x + 1 }; //完整标注的闭包定义
    let closures2 = |x| println!("{}", x + 1); //省略了类型注解,去掉了可选的大括号
    let num = closures2(1);//2
    
    // let num1 = closures2(1.0); //expected integer, found floating-point number
}

  

    (二)使用闭包实现两数交换值

fn main() {
    let closures = |mut x, mut y| {
        println!("交换前  x{} ,y{}", x, y);
        let mut temp = x;
        x = y;
        y = temp;
        println!("交换后  x{} ,y{}", x, y)
    };
    closures(1, 2);
}

console:

交换前  x1 ,y2
交换后  x2 ,y1

三,异同

(一)作用域不同

       闭包的定义:一个可以储存在变量里的类似函数的结构。闭包与变量是有相同的作用域,可以直接使用变量。而函数不可以

fn compare(x: i32, y: i32) {
    println!("{}", x == y);
}

fn main() {
    let a = 1;
    let compare1 = |x| println!("compare1{}", x == a);
    //无法直接获得a
    // fn compare2(z: i32) {
    //     println!("{}", x == a)
    // }
    //但可以传入来实现
    fn compare3(z: i32, a: i32) {
        println!("compare3{}", z == a)
    }
    compare1(1);
    compare3(1, a);
}

(二)三个特性(所有权,可变借用和不可变借用)一致

        闭包可以通过三种方式捕获其环境,他们直接对应函数的三种获取参数的方式:获取所有权,可变借用和不可变借用。

1,所有权

        如果你希望强制闭包获取其使用的环境值的所有权,可以在参数列表前使用 move 关键字。这个技巧在将闭包传递给新线程以便将数据移动到新线程中时最为实用。闭包只能获取相同变量的一次所有权。

    let y = "1".to_string();
    let compare1 = move |x: String| x.len() == y.len();
    // println!("{}", y); //borrow of moved value: `y`

    let z = "1".to_string();
    fn compare3(a: String, b: String) -> bool {
        a.len() == b.len()
    }
    compare3("1".to_string(), z);
    println!("{}", z);//borrow of moved value: `z`

2,借用

      从其环境获取不可变的借用值。虽然不能改变值,但可以在外层打印使用。

fn main() {
    let y = 1;
    let add = || {
        // y+=x;//不可操作
        println!("{}", y);
    };
    add();
    println!("{}", y);

    fn compare3(b: &i32) {
        // b+=1;//不可操作
        println!("{}", b);
    }
    let mut z = 2;
    compare3(&z);
    println!("{}", z);
}

3,可变借用

       可变的借用值所以可以改变其环境。

fn main() {
    let mut y = String::from("闭包  2");
    let mut add = |x: &str| {
        y.push_str(x);
    };
    add("+1");
    println!("{}", y);
    fn compare3(b: &mut String) {
        b.push_str("+2");
    }
    let mut z = String::from("函数 1");
    compare3(&mut z);
    println!("{}", z);
}

猜你喜欢

转载自blog.csdn.net/qq_39308071/article/details/113178669