[][src]Function tao_of_rust::ch06::closures::pass_closure

pub fn pass_closure()

闭包作为参数或返回值传递

Base usage: 闭包作为参数

fn boxed_closure(c: &mut Vec<Box<Fn()>>){
    let s = "second";
    c.push(Box::new(|| println!("first")));
    c.push(Box::new(move || println!("{}", s)));
    c.push(Box::new(|| println!("third")));
}
fn main(){
    let mut c: Vec<Box<Fn()>> = vec![];
    boxed_closure(&mut c);
    for f in c {
        f(); // first / second / third
    }
}Run

Base usage: 实现any方法,静态分发

注意:此处自定义Any,不同于标准库提供的Any

use std::ops::Fn;
trait Any {
    fn any<F>(&self,  f: F) -> bool where
    Self: Sized,
    F: Fn(u32) -> bool;
}
impl Any for Vec<u32> {
    fn any<F>(&self, f: F) -> bool where
    Self: Sized,
   F: Fn(u32) -> bool
   {
       for &x in self {
           if f(x) {
               return true;
           }
       }
       false
   }
}
fn main(){
    let  v = vec![1,2,3];
    let b = v.any(|x| x == 3);
    println!("{:?}", b);
}Run

Base usage: 函数指针也实现了Fn/FnMut/FnOnce

fn call<F>(closure: F) -> i32
where F: Fn(i32) -> i32
{
    closure(1)
}
fn counter(i: i32) -> i32 { i+1 }
fn main(){
    let result = call(counter);
    assert_eq!(2, result);
}Run

Base usage: 实现any方法,动态分发

注意:此处自定义Any,不同于标准库提供的Any

trait Any {
  fn any(&self,  f: &(Fn(u32) -> bool)) -> bool;
}
impl Any for Vec<u32> {
    fn any(&self, f: &(Fn(u32) -> bool)) -> bool {
        for &x in self.iter() {
            if f(x) {
                return true;
            }
       }
      false
   }
}
fn main(){
   let  v = vec![1,2,3];
   let b = v.any(&|x| x == 3);
   println!("{:?}", b);
}Run

Base usage: 只有逃逸闭包可装箱

fn main(){
    let s = "hello";
    let c: Box<Fn() + 'static> = Box::new( move||{ s;});
}Run

Base usage: 闭包作为返回值

fn square() -> Box<Fn(i32) -> i32> {
    Box::new(|i| i*i )
}
fn main(){
    let square = square();
    assert_eq!(4, square(2));
    assert_eq!(9, square(3));
}Run

Base usage: 闭包作为返回值 报错

fn square() -> Box<FnOnce(i32) -> i32> {
    Box::new( |i| {i*i })
}
fn main(){
    let square = square();
    assert_eq!(4, square(2));
}Run

Base usage: 使用FnBox修正

#![feature(fnbox)]
use std::boxed::FnBox;
fn square() -> Box<FnBox(i32) -> i32> {
    Box::new( |i| {i*i })
}
fn main(){
    let square = square();
    assert_eq!(4, square(2));
}Run

Base usage: 使用impl Trait

fn square() -> impl FnOnce(i32) -> i32 {
    |i| {i*i }
}
fn main(){
    let square = square();
    assert_eq!(4, square(2));
}Run