[rust-dev] Vectors, mutability & vec::dedup

Tom Lee rust-dev at tomlee.co
Thu Dec 13 00:17:29 PST 2012


Hey folks,

So turns out I'm still struggling with types a little. This time it's
related to mutability & function signatures. Apologies in advance if I
screw up terminology. Take the following code, which prints out the
unique elements of a vector:

extern mod std;
use std;

fn main() {
  let mut values = ~["foo", "bar", "foo", "baz"];

  do std::sort::quick_sort(values) |x, y| { str::le(*x, *y) }
  vec::dedup(&mut values);

  for vec::each(values) |v| { io::println(*v) }
}

I got this to compile & execute after several false starts, largely
via some educated guesses, but I'm still not convinced I fully
understand why this appeases the angry statically typed rustc gods. If
you good folks could weigh in & help me out it would be much
appreciated!

1. let mut values = ~["foo", "bar", "foo", "baz"];

Alright, so this is telling me that 'values' can be reassigned to some
other value (i.e. 'values' is a mutable variable). As near as I can
tell, because the 'mut' is on the left hand side, this appears to have
no impact on the actual type of 'values' except that the variable
itself be assigned different values in the local scope. Is that
correct?

2. vec::dedup(&mut values);

Here is where things get messy to me for all sorts of reasons. Looking
at the signature of vec::dedup:
http://dl.rust-lang.org/doc/core/vec.html#function-dedup I can see
that vec::dedup accepts a mutable, borrowed pointer to a ~[T]. I
*think* so that we can dig into the guts of the vector e.g.:

let p = p as *mut T
// snip ...
let _dropped = move *ptr::mut_offset(p, next_to_read);
// snip ...
*ptr::mut_offset(p, last_written) = move
                        *ptr::mut_offset(p, next_to_read);

It looks like the 'move' operations here are directly modifying the
contents of the vector by moving data around in the vector. This
strikes me as kind of strange. I've allocated an immutable vector on
the exchange stack and so make the assumption that the contents of the
vector is in effect fixed. Is that assumption cast to the wind as soon
as I start working with a mutable, borrowed pointer to that same
vector?

Or is this just the consequence of a bit of a sleazy optimization,
where the function signature makes it *look* like we're going to
return the deduped result in 'v' when in fact we're modifying it
in-place?

I'm not sure there's a coherent question here, but I feel like I'm
missing something. Hopefully somebody can understand what I'm rambling
on about & shed some light :)

Cheers,
Tom


More information about the Rust-dev mailing list