如何拥有一个接受来自另一个变量的闭包调用方法的结构?

How to have a struct that accepts closures calling methods from another variable?

所以我今年在做代码的出现,遇到了一个借用问题:

如何让结构接受闭包从另一个变量调用方法?这是我想出的一个最小示例。借用检查器不喜欢这两个闭包都借用值。

如果我有一个围绕值的互斥锁,那么它似乎可以工作,但我希望有一个更优雅的解决方案。

本质上,我希望不同的 Brains 具有不同的 input/output 功能,其中一个可能只打印输出,另一个可能将输出添加到 vec。

Playground link.

Actual code where I use it.

struct Brain<I, O>
where
    I: Fn() -> i32,
    O: FnMut(i32),
{
    input: I,
    output: O,
}

impl<I, O> Brain<I, O>
where
    I: Fn() -> i32,
    O: FnMut(i32),
{
    fn new(input: I, output: O) -> Self {
        Brain { input, output }
    }
}

fn runner() {
    let mut values = Vec::new();
    let request_input = || *values.last().unwrap();
    let add_output = |v| values.push(v);

    let _ = Brain::new(request_input, add_output);
}

你做错了,你显然不能在 rust 中这样做,你只能有一个可变引用或一个和多个引用,但不能同时有两个。与其使用像 MutexCell 这样的内部可变性,我建议你使用一个特征,例如你可以这样做:

trait Bus {
    fn input(&self) -> i32;
    fn output(&mut self, v: i32);
}

struct Brain<T>
where
    T: Bus,
{
    bus: T,
}

impl<T> Brain<T>
where
    T: Bus,
{
    fn new(bus: T) -> Self {
        Brain { bus }
    }
}

struct MyBus {
    values: Vec<i32>,
}

impl Bus for MyBus {
    fn input(&self) -> i32 {
        *self.values.last().unwrap()
    }

    fn output(&mut self, v: i32) {
        self.values.push(v)
    }
}

fn main() {
    let bus = MyBus { values: Vec::new() };

    let _ = Brain::new(bus);
}

这允许很大的灵活性。