Rust function & closure

函数与方法

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

impl Point{
    // 静态方法(static method)
    fn origin() ->Point {
        Point{ x:0.0,y:0.0}
    }

    fn new(x:f64,y:f64)->Point{
        Point{x:x, y:y}
    }
}


struct Rectangle{
    p1:Point,
    p2:Point,
}

impl Rectangle{
    // 实例方法(instance method)
    // area method 求面积
    fn area(&self)->f64{
        let Point{x:x1,y:y1} = self.p1;
        let Point{x:x2,y:y2} = self.p2;
        ((x1 -x2) * (y1 -y2)).abs()
    }

    // circumference 求周长
    fn circumference(&self) ->f64{
        let Point{x:x1,y:y1} = self.p1;
        let Point{x:x2,y:y2} = self.p2;
        2.0*((x1 -x2).abs() + (y1 -y2).abs())
    }

    fn translate(&mut self,x:f64,y:f64){
        self.p1.x +=x;
        self.p1.y +=y;

        self.p2.x +=x;
        self.p2.y +=y;
    }
}


struct Pair(Box<i32>,Box<i32>);

impl Pair{
    // 此方法会“消耗” 调用者的资源
    fn destroy(self){
        let Pair(first,second) = self;
        println!("Destroying Pair({}, {})", first, second);
    }
}

fn main() {
    let rectangle = Rectangle{
        // 静态方法使用双冒号调用
        p1:Point::origin(),
        p2:Point::new(3.0,4.0),
    };

    println!("Rectangle circumference:{}",rectangle.circumference());
    println!("Rectangle area:{}",rectangle.area());


    let mut square = Rectangle{
        p1:Point::origin(),
        p2:Point::new(1.0,1.0),
    };

    square.translate(1.0,1.0);
    println!("square area:{}",square.area());

    let pair = Pair(Box::new(1),Box::new(2));
    pair.destroy();
}

// Rectangle circumference:14
// Rectangle area:12
// square area:1
// Destroying Pair(1, 2)

闭包

Rust 中的闭包(closure),也叫做 lambda 表达式或者 lambda,是一类能够捕获周围作用域中变量的函数。

闭包允许变量捕获(capture)灵活地适应使用场合,既可移动(move)又可 借用(borrow)变量。闭包可以通过以下手段捕获变量:

  • Fn 通过引用: &T

  • FnMut通过可变引用: &mut T

  • FnOnce通过值: T

    译注:顺序之所以是这样,是因为 :
    &T 只是获取了不可变的引用,
    &mut T 则可以改变变量,
    T 则是拿到了变量的所有权而非借用。

use std::mem;

fn main() {
    let color = "green";
    let print = ||println!("color: {}", color);
    print();
    print();


    let moveable = Box::new(3);
    let consume = ||{
        println!("moveable: {:?}",moveable);
        mem::drop(moveable);
    };
    consume(); // 只能运行一次,不可复制类型(在堆上申请空间的数据类型)必须移动(move)到闭包中



    let stack = vec![1,2,3,4,5];
    let contains = move |needle|stack.contains(needle);
    println!("向量stack的容量是否包含1:=>{}",contains(&1));
    println!("向量stack的容量是否包含6:=>{}",contains(&6));
}

// color: green
// color: green
// moveable: 3
// 向量stack的容量是否包含1:=>true
// 向量stack的容量是否包含6:=>false

示例二
以下的示例,将函数(闭包)作为参数传入函数中。

use std::mem;

//该函数将闭包作为参数并调用它
fn apply<F>(f:F) where
    //闭包没有输入值和返回值
    F:FnOnce(){
    f();
}

fn apply_to_3<F>(f:F)->i32 where
    F: Fn(i32) ->i32{
    f(3)
}

fn main() {
    let greeting = "hello";
    let mut farewell = "goodbye".to_owned();
    let diary = ||{
        println!("I said {}.",greeting);  // `greeting`通过引用捕获,故需要闭包是`Fn`

        farewell.push_str("!!!");   // 改变了`farewell`,闭包通过可变引用来捕获它,需要`FnMut`。
        println!("Then I screamed {}.",farewell);

        mem::drop(farewell);           //手动调用drop,闭包通过值获取`farewell`(包括所有权)。需要`FnOnce`
    };

    apply(diary);


    let double = |x| {2*x};
    println!("3 double: {}",apply_to_3(double));
}

// I said hello.
// Then I screamed goodbye!!!.
// 3 double: 6
输入函数
fn call_me<F:Fn()>(f:F){
    f()
}

fn function(){
    println!("I'm a function!!!");
}

fn main(){
    let closure = ||println!("I am a closure!");
    call_me(closure);
    call_me(function);
}
// I am a closure!
// I'm a function!!!
作为输出参数

目前 Rust 只支持返回具体(非泛型)的类型
按照定义,匿名的闭包的类型是未知的,所以只有使用 impl Trait 才能返回一个闭包

必须使用 move 关键字(捕获都是通过值进行),因为在函数退出时,任何通过引用的捕获都被丢弃,防止在闭包中留下无效的引用。

示例(返回闭包(函数))

fn create_fn() ->impl Fn(){
    let text = "zhangsan".to_owned();
    move||println!("This is a {}",text)
}

fn create_fnmut()-> impl FnMut(){
    let text = "lisi".to_owned();
    move||println!("This is a {}",text)
}

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

    fn_plain();
    fn_mut();
}
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页