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

Nicholas Bishop nicholasbishop at gmail.com
Sun Jun 1 15:32:36 PDT 2014


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

An interesting suggestion, but doesn't extend easily to other types of
containers like HashMaps.

> 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.

I'll give that a try. It should be enough to get me past immediate
problems at least.

-Nicholas

>>
>> 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
>
>
>
> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>


More information about the Rust-dev mailing list