【问题标题】:Save Vec after pattern match模式匹配后保存 Vec
【发布时间】:2017-05-02 08:37:43
【问题描述】:

我正在使用 robots crate 中的 Actor 特征:

extern crate robots;    

use std::any::Any;
use robots::actors::{Actor, ActorCell};


#[derive(Clone, PartialEq)]
pub enum ExampleMessage {
    Test { data: Vec<u8> },
}

pub struct Dummy {
    data: Vec<u8>,
}

impl Actor for Dummy {
    // Using `Any` is required for actors in RobotS
    fn receive(&self, message: Box<Any>, _context: ActorCell) {
        if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
            match *message {
                ExampleMessage::Test { data } => {
                    self.data = data; // cannot assign to immutable field
                    println!("got message")
                }
            }
        }
    }
}

impl Dummy {
    pub fn new(_: ()) -> Dummy {
        let data = Vec::new();
        Dummy { data }
    }
}

错误:

error: cannot assign to immutable field `self.data`
  --> <anon>:18:21
   |
18 |                     self.data = data; // cannot assign to immutable field
   |                     ^^^^^^^^^^^^^^^^

我了解为什么我当前的代码不起作用,但我不知道保存传入数据 (Vec) 的最佳方法是什么,以便我的 Dummy 以后可以访问它。

【问题讨论】:

    标签: rust pattern-matching message-passing


    【解决方案1】:

    您在这里遗漏了一个简单的点:您的方法 receive()&amp;self 作为参数。您不能通过&amp;self 修改self 对象,因为它是一个不可变 引用。要更改 self 的任何字段,请接受可变引用 (&amp;mut self) 或 - 如果无法绕过它 - 使用内部可变性。示例:

    fn receive(&mut self, message: Box<Any>) {
        // ...
        self.data = data;  // works
        // ...
    }
    

    但是,如果您无法更改 Actor 实现的 Dummy 特征,那么在您的情况下这可能是不可能的。在这种情况下,您必须使用interior mutability,例如RefCell&lt;Vec&lt;u8&gt;&gt;。但是,如果您可以改变特征,请考虑这样做。 receive() 方法听起来已经像 self 对象应该更改以产生任何效果。

    如果这不仅仅是你的一个粗心错误,请务必阅读 Rust 书中关于 BorrowingMutability 的章节,因为这对 Rust 非常重要。

    【讨论】:

    • 我正在实现 Actor trait impl Actor for Dummy。因为我正在实现 trait,所以我不能使引用可变,因为这会导致不兼容的类型错误。
    • 我不能使用 RefCell,因为它不满足 trait bound std::marker::Sync。我在机器人的 github 存储库中找到了 test。我必须使用互斥锁,我将在今天晚些时候自己写答案。
    【解决方案2】:

    我在 RobotS github 存储库中找到了一个 test,它显示了如何管理 Actor 的内部状态。 必须将状态封装在 Mutex 中以进行线程安全访问:

    extern crate robots;    
    
    use std::any::Any;
    use std::sync::Mutex;
    use robots::actors::{Actor, ActorCell};
    
    
    #[derive(Clone, PartialEq)]
    pub enum ExampleMessage {
        Test { data: Vec<u8> },
    }
    
    pub struct Dummy {
        data: Mutex<Vec<u8>>,
    }
    
    impl Actor for Dummy {
        // Using `Any` is required for actors in RobotS
        fn receive(&self, message: Box<Any>, _context: ActorCell) {
            if let Ok(message) = Box::<Any>::downcast::<ExampleMessage>(message) {
                match *message {
                    ExampleMessage::Test { data } => {
                        let mut my_data = self.data.lock().unwrap();
                        *my_data = data;
                        println!("got message")
                    }
                }
            }
        }
    }
    
    impl Dummy {
        pub fn new(_: ()) -> Dummy {
            let data = Mutex::new(Vec::new());
            Dummy { data }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2020-02-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-04
      • 2018-04-07
      • 2020-02-09
      • 2019-11-05
      相关资源
      最近更新 更多