Как определить признак индекса для объекта, в котором данные хранятся в RefCell в Rust? - PullRequest
1 голос
/ 18 октября 2019

Как определить черту Index для объекта, в котором данные хранятся в RefCell в Rust? По сути, у меня есть объект, который я хотел бы проиндексировать, где иногда существуют данные, а иногда нет. Когда данных не существует, я хотел бы создать их, а затем вернуть соответствующую ссылку для операции индексации. В противном случае я бы хотел индексировать как обычно. В качестве упрощенного примера этого у нас есть код

// External libraries                                                            
use std::cell::{Ref, RefCell};                                                   
use std::ops::Index;                                                             

// Funny looking vector                                                          
struct MyVec<T> {                                                                
    size: usize,                                                                 
    data: RefCell<Option<Vec<T>>>,                                               
}                                                                                

// Create a full vector                                                          
fn full<T>(size: usize, data: Vec<T>) -> MyVec<T> {                              
    MyVec {                                                                      
        size,                                                                    
        data: RefCell::new(Some(data)),                                          
    }                                                                            
}                                                                                
// Creates an empty vector                                                       
fn empty<T>(size: usize) -> MyVec<T> {                                           
    MyVec {                                                                      
        size,                                                                    
        data: RefCell::new(None),                                                
    }                                                                            
}                                                                                

// Index from the vector                                                         
impl<T> Index<usize> for MyVec<T>                                                
where                                                                            
    T: Clone + Default,                                                          
{                                                                                
    type Output = T;                                                             
    fn index(&self, idx: usize) -> &Self::Output {                               
        // Take out the data for processing                                      
        let data = self.data.replace(None);                                      

        // Make sure the data is full                                            
        let data = match data {                                                  
            None => Some(vec![Default::default(); self.size]),                   
            Some(_) => data,                                                     
        };                                                                       

        // Put the data back inside the vector                                   
        let _ = self.data.replace(data);                                         

        // Return a reference to the element                                     
        Ref::map(self.data.borrow(), |data| match &data {                        
            Some(data) => &data[idx],                                            
            None => unreachable!(),                                              
        })                                                                       
    }                                                                            
}                                                                                

// Test our functions                                                            
fn main() {                                                                      
    // Create an empty vector                                                    
    let a = empty::<f32>(3);                                                     

    // Print a value                                                             
    println!("a(1): {}", a[1]);                                                  
} 

. Он не компилируется и возвращает ошибку:

error[E0308]: mismatched types
  --> src/test02.rs:48:9
   |
48 | /         Ref::map(self.data.borrow(), |data| match &data {
49 | |             Some(data) => &data[idx],
50 | |             None => unreachable!(),
51 | |         })
   | |__________^ expected &T, found struct `std::cell::Ref`
   |
   = note: expected type `&T`
              found type `std::cell::Ref<'_, T>`
help: consider borrowing here
   |
48 |         &Ref::map(self.data.borrow(), |data| match &data {
49 |             Some(data) => &data[idx],
50 |             None => unreachable!(),
51 |         })
   |

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

Конечно, Ref не совпадает с &. Тем не менее, как это можно исправить?

В случае, если это имеет значение, мне не обязательно нужно a RefCell. На самом деле, у меня есть тип перечисления с различными параметрами. Тем не менее, дело остается тем же. Иногда данные существуют. Иногда данные не. Когда данных не существует, я хотел бы создать их до того, как мы их проиндексируем.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...