I have a problem I found a solution to but it is so ugly that there must be a better "idiomatic" way to solve it (I'm from a C++/Java background so I still fell the urge to make everything classes ...)
I have a method/functions which gets a problem with referencing mutable variables in the struct together with an mutable "self" reference.
The structure is something like this
pub struct A { map: BtreeMap<...>, }
impl A {
fn helper1(&self, ...) { ... }
fn helper2(&mut self, &mut map_entry ...) {
// Some work that adjusts struct entry "map_entry"
self.helper1( &self, ...);
}
fn func1(&mut self, ...) {
// Get some reference to a specific BTreeMap entry last_entry()
self.helper2( self.map.get_last() );
// Cleaning up etc.
}
fn func2(&mut self, ...) {
// Get some other reference to a specific BTreeMap entry first_entry()
self.helper2( self.map.get_first() );
// Cleaning up etc.
}
fn func3(&mut self, ...) {
self.helper2( ... some other calculations to determine map entry ...);
}
}
Now, this will (of course) fail with a "Cannot borrow *self as mutable more than once ..." in func1,2,3() as I have both self and the variable from the struct (entry from the BTreeMap) as mutable. I fully (I think ...) understand the problem.
This reason for this error is me trying to break it down in multiple methods as a lot of the work can be factored out in the helper2() method which can be used from func1,2,3() and also wanting to keep it as a "class" method.
I can fix this in two ways
- duplicate code to avoid having to make calls to other methods and thereby avoiding the "self" borrow issue
- make all the helper methods into static functions to be called as
A::helper2()and not having a "self" being borrowed more than one time in thefunc1,2,3()as they have no need to access any internal struct variables.
As I don't want to duplicate code I solved it with Method 2).
However, this seems quite "ugly" to me having to mix static functions with "class/object" functions.
Is it possible to give some generic advise (without having to go into more specific details in my case) about the idiomatic way to handle this more generic issue. It feels like this use case or situation wouldn't be that uncommon?
selfif not needed is quite idiomatic. Perhaps even make them free functions.self, you can pass the fields as separate parameters. Alternatively, a trick you can use is to remove the entry from the map, then re-insert it.Self::helper2()instead ofA::helper2(), which is significantly shorter ifAhas a long name and/or a bunch of generics. (Also, it makes it crystal-clear that you're invoking a non-self-taking method on the same type.)