Erick Tryzelaar wrote:
Well, we need the MutableMap-style traits, but we could fold the
ImmutableMap-style "insert into a copy" methods to Map. I don't think
we can rely on "&mut self" helping us out because it could be a source
of bugs. For example, if w forget a hashmap is currently immutable and
do "m.remove(x);" nothing actually happened.
One idea regarding remove and friends would be to structure the traits
something like this.
First there would be your basic `Map` trait that assumes operations take
effect "in-place":
trait Map<K,V> {
fn add(&mut self, k: K, v: V);
fn remove(&mut self, k: &K);
...
}
In a persistent map, there must be some other operation that returns a
new map, let's call them plus and minus:
trait PersistentMap<K,V> : Map<K,V> {
fn plus(&self, k: K, v: V) -> self;
fn minus(&self, k: &K) -> self;
...
}
In that case, add and remove can be implemented in terms of plus and
minus fairly easily:
trait PersistentMap<K,V> : Map<K,V> {
...
fn add(&mut self, k: K, v: V) { *self = self.plus(k, v); }
fn minus(&mut self, k: &K) { *self = self.minus(k); }
}
Here I am assuming an impl something like:
impl<K,V> PersistentMap<K,V> for @PersistentHashMap<K,V> {
...
}
Note that `@` sign in the impl. I think this would be required for this
scheme to work out.
The neat thing about this is that persistent maps can be used anywhere a
"normal" map is expected. In fact, you'll note that *persistent maps*
and *freezable maps* work pretty similarly. That is, if I have a
function like this:
fn do_something<M:Map<int,int>>(m: M) { ... }
If `m` is a freezable map, like send_map, then `m` is *consumed* by
`do_something()` and thus the caller of `do_something()` can never see
the changes that `do_something()` made. If `m` is a persistent map, the
same is true, except that the caller may hold on to its original copy of
`m`---but in any case the caller cannot see what `do_something()` has
done. If `do_something()` wants its changes to be visible to the
caller, it should be declared with a borrowed pointer:
fn do_something<M:Map<int,int>>(m: &mut M) { ... }
Basically what I'm getting at here is that both *freezable* and
*persistent* maps share the property that they *act like immutable
values*. This is true *even though* freezable maps are modified
in-place, because *at the time of modification* no aliases exist, so
who's to say you didn't swap in a new map?
Niko
_______________________________________________
Rust-dev mailing list
[email protected]
https://mail.mozilla.org/listinfo/rust-dev