2014-01-27 2 views
6

Я пытаюсь написать структуру контейнера в Rust, где его элементы также хранят ссылку на содержащий контейнер, чтобы они могли вызывать на нем методы. Насколько я мог понять, мне нужно сделать это через Rc<RefCell<T>>. Это верно?Ссылка на содержащую структуру в Rust (и методы вызова на нем)

До сих пор, у меня есть что-то вроде следующего:

struct Container { 
    elems: ~[~Element] 
} 

impl Container { 
    pub fn poke(&mut self) { 
    println!("Got poked."); 
    } 
} 

struct Element { 
    datum: int, 
    container: Weak<RefCell<Container>> 
} 

impl Element { 
    pub fn poke_container(&mut self) { 
    let c1 = self.container.upgrade().unwrap(); // Option<Rc> 
    let mut c2 = c1.borrow().borrow_mut(); // &RefCell 
    c2.get().poke(); 
// self.container.upgrade().unwrap().borrow().borrow_mut().get().poke(); 
// -> Error: Borrowed value does not live long enough * 2 
    } 
} 

fn main() { 
    let container = Rc::new(RefCell::new(Container{ elems: ~[] })); 
    let mut elem1 = Element{ datum: 1, container: container.downgrade() }; 
    let mut elem2 = Element{ datum: 2, container: container.downgrade() }; 
    elem1.poke_container(); 
} 

Я чувствую, что я пропускаю что-то здесь. Является ли доступ к содержимому Rc<RefCell<T>> действительно сложным (в poke_container)? Или я подхожу к проблеме не так?

И наконец, если предположить, что подход является правильным, как бы я написать add метод Container так, чтобы он мог заполнить container поле в Element (предполагая, что я изменил поле, чтобы иметь тип Option<Rc<RefCell<T>>>? Я не могу создать другой Rc от &mut self 0 насколько я знаю.

+1

BTW, нет необходимости использовать '~ [~ Element]' вместо '~ [Element]'. –

+0

@ Vladimir Правда, спасибо, но в моем фактическом коде «Элемент» - это черта, поэтому я думаю, что я не могу оставить «~» в этом случае. – Kolja

+1

Да, вы правы, в этом случае вам понадобится '~'. Что касается вопроса, я не вижу, как вы могли бы упростить доступ к содержимому окна «Rc». Вот как это работает сейчас. Хотелось бы надеяться, что было бы проще, когда реальный «Gc» приземлится (так что не понадобится обертка «Weak»), и когда будет доступно избыточное разыменование (никаких дополнительных вызовов «заимствования» и «заимствования»)(). –

ответ

1

Длинная цепочка вызовов методов действительно работает для меня на главном без каких-либо изменений, поскольку время жизни «r-значений» (например, результат вызовов функций) изменилось так что временные значения возврата продолжаются до конца инструкции, а не до конца следующего вызова метода (который, казалось, работал с старым правилом).

Как намекает Владимир, Перегружаемые разыменования, скорее всего, уменьшить его

self.container.upgrade().unwrap().borrow_mut().poke(); 

, который лучше.

В любом случае, «мутирующая» совместная собственность всегда будет (слегка) сложнее писать в Rust, что либо один код собственности, либо неизменный код совместного владения, потому что такой код очень небезопасен для памяти (и безопасность памяти является основной целью Rust).

 Смежные вопросы

  • Нет связанных вопросов^_^