应用篋:闭包借用实例

学习内容

  • 了解和学习Rust语言闭包借用实例

篇目

理解Rust语言闭包

  闭包(closure)是现代计算机语言发展起来的重要技术,它延伸了传统计算机语言函数的概念。Rust语言中的闭包(也称为lambda表达式或lambda,)是可以捕获封闭环境的函数。传统函数就是一个独立的和重复使用的功能性代码单位,它通过被调用而与其它代码进行交互。而闭包不仅可以被其它代码调用;而且其代码块本身也可以直接与其封闭环境内的代码进行交互,捕获外部环境变量的能力,而这一点传统函数没有这样的功能。

  闭包与函数比较说明:

  • 闭包可以捕获外部环境变量的能力,而函数不能;
  • 传递到闭包的输入参数。使用||,而不是像函数()一样;
  • 闭包代码块也使用函数一样的{},但是函数是强制性使用,而闭包在一些情况下是可选性使用;
  • 输入参数的类型也是可选的,而非函数是强制的;
  • 闭包不存在闭包名,而函数不能,甚至闭包连绑定变量也可以不要;
  • 调用闭包不仅与函数有完全一样的方式,而且还存在闭包自身特殊方式;
  • 闭包输出的表达方式与函数完全一样;
  • 闭包返回方式与函数完全一样;

  将上面比较说明,对照下面实例代码。方法main()的第二行代码,第一,定义了闭包,且绑定到变量i_am_closure,可以理解为“闭包名”;第二,把第一行代码这种外部变量outside_closure应用到闭包代码块内部;第三,输入参数input_var省略了类型名称,之所以可以省略,是因为第一行代码定义了输入参数的类型。第三行代码里存在调用第二行定义的闭包代码。

fn main() {
    let outside_closure = 21u8;
    let i_am_closure = |input_var| -> u8 { input_var + outside_closure };
    println!("i_am_closure: {}", i_am_closure(outside_closure));
}

闭包实例

  通过下面实例来进一步理解闭包使用方法。这个实例看起来比较抽象,这一行代码连一个字母都没有。但这是理解闭包很好的代码。

fn main(){
    (|__:()|->(){__})(())
}

  通过下面程序代码逐步展开来解析上面程序的含义。程序里每一段代码都是一样的功能,从上到下还原到可以比较理解的代码。

  需要说明的是,在方法main()里,前面四段代码,既定义了闭包,同时也调用了闭包。只有第五段代码定义与调用分成了两个语句。


# #![allow(unused_variables)]
#fn main() {
    // File: lib-hello/src/immut/closure/mod.rs
    // Function: use_closure()
    (|__: ()| -> () { __ })(());

    (|input_var: (bool)| -> (bool) { input_var })((true));

    |input_var: (bool)| -> (bool) { input_var }((true));

    let tuple = (true);
    |input_var: (bool)| -> (bool) { input_var }(tuple);

    let tuple = (true);
    let closure_instance = |input_var: (bool)| -> (bool) { input_var };
    closure_instance(tuple);
#}

未实现复制特质Copy类型的借用实例

  下面代码说明字符串类型String对象作为闭包参数使用以后,其生命周期结束的实例。变量作为闭包参数使用以后,在闭包里,进行了一次变量的复制,导致了Rust语言所示的移动move,实际上,在闭包完成调用以后,该变量从内存里被剔除掉了。


# #![allow(unused_variables)]
#fn main() {
    // File: ./bin-hello/examples/closure/immut_string/mod.rs
    // #[cfg(feature = "err_01")]

    let string_instance: String = "Hello".to_string();

    let closure_instance = |hello: String| println!("{} Friend!", hello);
    closure_instance(string_instance);

    println!("{} World!", string_instance);

#}

借用机制代码实例

  解决上面实例的方法,与前面一节函数方法一样,使用引用类型对象。传递到闭包里,而不是类型字符串对象。引用变量对象仅仅是利用了类型字符串对象的内容而已,闭包本身实际上没有与类型字符串对象发生联系。


# #![allow(unused_variables)]
#fn main() {
    // File: ./bin-hello/examples/closure/immut_string/mod.rs
    // #[cfg(feature = "ok")]

    let string_instance: String = "Hello".to_string();

    println!("Before fn = {:p}", &string_instance);
    let closure_instance = |hello: &str| {
        println!("{} Friend!", hello);
        println!("Inside fn = {:p}", &hello);
    };
    closure_instance(&string_instance);
    println!("After fn = {:p}", &string_instance);

    println!("{} World!", string_instance);

#}

题外话

参考资料