danielpclark / rutie

“The Tie Between Ruby and Rust.”
MIT License
940 stars 62 forks source link

Mutable wrappable objects #116

Closed Zapotek closed 4 years ago

Zapotek commented 4 years ago

Is there any way to have mutable wrappable objects? Maybe add a wrappable_mutable_struct! macro that uses a Mutex for the lazy-static part?

danielpclark commented 4 years ago

Can you give more details and an example scenario?

Zapotek commented 4 years ago

Here's an example scenario:

#[allow(useless_attribute)]
use std::hash::{Hash};

use std::collections::BTreeSet;
use std::panic;
use rutie::types::Value;
use rutie::{Array, Class, Fixnum, Object, AnyObject, Boolean};

#[derive(Hash)]
#[derive(PartialEq)]
pub struct Set {
    collection: BTreeSet<usize>
}

impl Set {

    fn new() -> Self {
        Set {
            collection: BTreeSet::new()
        }
    }

    fn insert( &mut self, item: usize ) -> &Set {
        self.collection.insert( item );
        self
    }

}

fn _set_new_ext() -> AnyObject {
    Class::new( "Set", None ).wrap_data( Set::new(), &*SET_WRAPPER )
}

fn _set_insert_ext( _itself: &SetExt, item: usize ) -> AnyObject {
    _itself.get_data( &*SET_WRAPPER ).insert( item );
    _itself.to_any_object()
}

wrappable_struct!( Set, SetWrapper, SET_WRAPPER );

class!( SetExt );
unsafe_methods!(
    SetExt,
    _itself,

    fn set_new_ext() -> AnyObject {
        _set_new_ext()
    }

    fn set_insert_ext( item: Fixnum ) -> AnyObject  {
        _set_insert_ext( &_itself, item.value().value  )
    }

);

pub fn initialize() {
    Class::new( "Set", None ).define(|itself| {
        _itself.def_self( "new", set_new_ext );
        _itself.def( "<<",       set_insert_ext );
    });
}
error[E0596]: cannot borrow data in a `&` reference as mutable
  --> src/support/set.rs:37:5
   |
37 |     _itself.get_data( &*SET_WRAPPER ).insert( item );
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot borrow as mutable
Zapotek commented 4 years ago

Is this a feature you'd be interested in implementing? I believe It would be immensely helpful.

Zapotek commented 4 years ago

Hello again,

This is currently blocking me so I'd appreciate a response, I could work around the issue but it would result in much less elegant design and more memory and CPU usage.

This example just showcases the core issue of immutability, in reality I'd like to do some heavy-duty processing on Rust's side and keep it there, in essence I'd like to avoid having to pass a lot of data back-and-forth.

Cheers

danielpclark commented 4 years ago

Hey @Zapotek, the wrappable structs is the one part of this code I've touched the least since inheriting this project. If you'd like to have a crack at implementing this feature yourself I'd welcome the PR.

Zapotek commented 4 years ago

I've tried but failed miserably, sadly I'm not that well versed in Rust yet.

Zapotek commented 4 years ago

I've put a bounty on this in case you're interested.

Zapotek commented 4 years ago

For others trying to work around the issue, what I've done to bypass this limitation is use Rc<RefCell<BTreeSet<usize>>>, but a cleaner Rutie feature would be preferable I think.

dervus commented 4 years ago

@Zapotek could you explain why your case can't use get_data_muf to get mutable borrow? There is even an example[1] in wrappable_struct! documentation. Also, the underlying binding::class::get_data function[2] always returns &mut T.

[1] https://github.com/danielpclark/rutie/blob/master/src/dsl.rs#L569-L656 [2] https://github.com/danielpclark/rutie/blob/master/src/binding/class.rs#L104-L116

Zapotek commented 4 years ago

I'm about to seriously facepalm, I was looking through the docs but completely missed get_data_mut because it wasn't necessary with Ruru.

I'll give that a go, thanks for pointing me to the right direction @dervus.

kitlith commented 4 years ago

@Zapotek did get_data_mut work for you?

Zapotek commented 4 years ago

Yes it did, I can't believe I missed it.

Thank you all for your help.