多个closure引用同一个变量,并且可能需要mut borrow

目前在实现一个事件系统,事件采用保存closure的方式实现,这其中遇到一个比较棘手的问题就是如果其中一个closure用&mut方式捕捉了一个变量,那么其他closure就不可以再用任何方式捕捉这个变量(rust的borrow check系统),并且如果要&mut捕捉还需要把closure的类型写成FnMut,类似这种: add_event<F>(&mut self,f:F) where F:FnMut(...){}
目前折中的一个方法就是用Rc<RefCell<T>>的方式了,这个就是最终用户用起来很烦,大量的变量要用这种方式包裹。

use std::rc::Rc;
use std::cell::RefCell;

enum MyCall<'a>{
    Click(Box<Fn(i32)->i32 + 'a>),
    Down(Box<Fn(i32,i32)->i32 + 'a>),
    None,
}

struct Foo<'a>{
    calls:Vec<MyCall<'a>>,
}

impl<'a> Foo<'a>{
    fn new()->Foo<'a>{
        Foo{
            calls:Vec::new(),
        }
    }

    fn add_click<F>(&mut self,f: F)where F:Fn(i32)->i32+'a{
        self.calls.push(MyCall::Click(Box::new(f)));
    }

    fn do_call(&self){
        if let MyCall::Click(ref c) = self.calls[0] {
                println!("{}",(*c)(100));
        }

        if let MyCall::Click(ref c) = self.calls[1] {
                println!("{}",(*c)(100));
        }
    }
}

#[derive(Debug)]
struct A(i32);

#[derive(Debug)]
struct Bar{
    i:Rc<RefCell<A>>,
}

fn main(){
    let mut b = Bar{i:Rc::new(RefCell::new(A(200)))};
    let mut f = Foo::new();
    f.add_click(|i|{
        let bi = b.i.clone();
        let mut mbi = bi.borrow_mut();
        (*mbi).0 = 2000;
        (*mbi).0
        //b.0 = 100;
        //b.0
    });
    f.add_click(|i|{
        let bi = b.i.clone();
        let mut mbi = bi.borrow_mut();
        (*mbi).0 = 20000;
        (*mbi).0
    });
    f.do_call();
    println!("{:?}",b);
}

Play地址:http://is.gd/vdtWiG

输出:

2000
20000
Bar { i: RefCell { value: A(20000) } }

其实不用Rc也可以,大家可以看看这个,我目前对这个机制也不是太熟悉:
http://is.gd/78HF1Y

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值