[rust-dev] Calling a method while iterating over a field of the object

Brandon Sanderson singingboyo at gmail.com
Sun Jun 1 14:33:36 PDT 2014


I haven't tried this at all, but could iterating over the range [ 0,
g.edges.len() ) work?


On Sun, Jun 1, 2014 at 2:26 PM, Cameron Zwarich <zwarich at mozilla.com> wrote:

> 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 <nicholasbishop at gmail.com>
> 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 <zwarich at mozilla.com>
> 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
> >> <christophe.pedretti at gmail.com> wrote:
> >>
> >> and using mut_iter() instead of iter() is not enough ?
> >>
> >>
> >> 2014-06-01 22:03 GMT+02:00 Cameron Zwarich <zwarich at mozilla.com>:
> >>>
> >>> 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 <
> nicholasbishop at gmail.com>
> >>>> 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
> >>>> Rust-dev at mozilla.org
> >>>> https://mail.mozilla.org/listinfo/rust-dev
> >>> _______________________________________________
> >>> Rust-dev mailing list
> >>> Rust-dev at mozilla.org
> >>> https://mail.mozilla.org/listinfo/rust-dev
> >>
> >>
> >> _______________________________________________
> >> Rust-dev mailing list
> >> Rust-dev at mozilla.org
> >> https://mail.mozilla.org/listinfo/rust-dev
> >>
> >>
> >>
> >> _______________________________________________
> >> Rust-dev mailing list
> >> Rust-dev at mozilla.org
> >> https://mail.mozilla.org/listinfo/rust-dev
> >>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20140601/0b71fe91/attachment.html>


More information about the Rust-dev mailing list