It’s difficult to do something better without somewhat breaking the encapsulation of your graph type, but you could split G into edge and vertex data structures and have the functions that add vertices / edges operate on part of . Then given an &mut G, you could reborrow the vertex data and the edge data with &mut pointers separately.
This is tricky because not all implementations of a graph interface allow separate modification of vertex and edge data, so to exploit this you have to expose your representation somewhat. Cameron On Jun 1, 2014, at 2:15 PM, Nicholas Bishop <[email protected]> wrote: > Building an intermediate would work, but it implies extra overhead. If > this was a large graph instead of just one edge then it could be > expensive to copy from the intermediate back into the original object. > Are there any alternatives to consider? > > On Sun, Jun 1, 2014 at 4:48 PM, Cameron Zwarich <[email protected]> wrote: >> `mut_iter` only gives you mutable references to the elements of the >> container; it doesn’t allow you to reborrow the container itself mutably >> inside of the loop. >> >> Cameron >> >> On Jun 1, 2014, at 1:39 PM, Christophe Pedretti >> <[email protected]> wrote: >> >> and using mut_iter() instead of iter() is not enough ? >> >> >> 2014-06-01 22:03 GMT+02:00 Cameron Zwarich <[email protected]>: >>> >>> The simplest thing to do is probably to build an intermediate vector of >>> vertices to insert and then push them all after you are done iterating over >>> the edges. >>> >>> Cameron >>> >>>> On Jun 1, 2014, at 12:48 PM, Nicholas Bishop <[email protected]> >>>> wrote: >>>> >>>> I'm looking for a little borrow-checker advice. Here's a reasonably >>>> minimal program that demonstrates the problem: >>>> >>>> extern crate collections; >>>> >>>> use collections::HashMap; >>>> >>>> struct G { >>>> verts: HashMap<int, String>, >>>> edges: Vec<(int, int)>, >>>> >>>> next_vert_id: int >>>> } >>>> >>>> impl G { >>>> fn new() -> G { >>>> G{verts: HashMap::new(), edges: Vec::new(), next_vert_id: 0} >>>> } >>>> >>>> fn add_vert(&mut self, s: &str) -> int { >>>> let id = self.next_vert_id; >>>> self.next_vert_id += 1; >>>> self.verts.insert(id, String::from_str(s)); >>>> id >>>> } >>>> >>>> fn add_edge(&mut self, v0: int, v1: int) { >>>> self.edges.push((v0, v1)) >>>> } >>>> } >>>> >>>> fn main() { >>>> let mut g = G::new(); >>>> >>>> { >>>> let v0 = g.add_vert("vert 0"); >>>> let v1 = g.add_vert("vert 1"); >>>> g.add_edge(v0, v1); >>>> } >>>> >>>> for &(v0, v1) in g.edges.iter() { >>>> g.add_vert("edge vert"); >>>> } >>>> } >>>> >>>> This fails to compile: >>>> $ rust-nightly-x86_64-unknown-linux-gnu/bin/rustc -v >>>> rustc 0.11.0-pre-nightly (064dbb9 2014-06-01 00:56:42 -0700) >>>> host: x86_64-unknown-linux-gnu >>>> >>>> $ rust-nightly-x86_64-unknown-linux-gnu/bin/rustc graph.rs >>>> graph.rs:39:9: 39:10 error: cannot borrow `g` as mutable because >>>> `g.edges` is also borrowed as immutable >>>> graph.rs:39 g.add_vert("edge vert"); >>>> ^ >>>> graph.rs:38:22: 38:29 note: previous borrow of `g.edges` occurs here; >>>> the immutable borrow prevents subsequent moves or mutable borrows of >>>> `g.edges` until the borrow ends >>>> graph.rs:38 for &(v0, v1) in g.edges.iter() { >>>> ^~~~~~~ >>>> graph.rs:41:2: 41:2 note: previous borrow ends here >>>> graph.rs:38 for &(v0, v1) in g.edges.iter() { >>>> graph.rs:39 g.add_vert("edge vert"); >>>> graph.rs:40 } >>>> graph.rs:41 } >>>> ^ >>>> error: aborting due to previous error >>>> >>>> My understanding of the error is: G::add_vert is being given a mutable >>>> reference to "g", which means it could do something naughty like clear >>>> g.edges, which would screw up the loop iteration that is happening in >>>> main(). >>>> >>>> That seems like a pretty reasonable thing to prevent, but it's not >>>> clear to me how I should restructure the program to work around the >>>> error. In this minimal example I could copy the code out of >>>> G::add_vert and stick it directly inside the loop, but that's clearly >>>> not the general solution. >>>> >>>> Thanks, >>>> -Nicholas >>>> _______________________________________________ >>>> Rust-dev mailing list >>>> [email protected] >>>> https://mail.mozilla.org/listinfo/rust-dev >>> _______________________________________________ >>> Rust-dev mailing list >>> [email protected] >>> https://mail.mozilla.org/listinfo/rust-dev >> >> >> _______________________________________________ >> Rust-dev mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/rust-dev >> >> >> >> _______________________________________________ >> Rust-dev mailing list >> [email protected] >> https://mail.mozilla.org/listinfo/rust-dev >> _______________________________________________ Rust-dev mailing list [email protected] https://mail.mozilla.org/listinfo/rust-dev
