-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add find_or_insert method to the Map trait #5568
Comments
Agreed. Also several of the other ones that appear on hashmap: |
@graydon: I think |
I'm working on this. I'm trying to add default methods where possible, swap can be implemented in terms of
Any preferences between those or other suggestions? |
I don't think there should be a default method implementation if it's going to do two searches but I'm fine with both of the other options. |
Perhaps we can just add "mangle" to the map trait and impl the others as default methods based on that? |
First, sorry for saying I was going to do this and sitting on it for so long. I keep meaning to make time to try to help out with rust but getting busy with other things. I still plan to try to get this done. How about changing
That seems nicer than |
Interesting thought! I agree that mangle is clunky and awkwardly named (despite being the one who suggested it). I would also consider just modifying the callback for |
@davidhalperin : are you still working on that? I am interested in working on this issue. Maybe we can work together? |
@TeXitoi sorry for not getting back to you. I have Monday off and I think I should have a good chunk of time to work on this this weekend. By the end of the day on Monday I'll either finish this and put together a pull request or pass what I've done so far on to you to finish up. Sound good? |
@davidascher Perfect :) |
I got very close to finishing it this weekend. The one thing I couldn't figure out is how to write |
IMHO, it's not possible to do that with safe code without doing an insert and then a find (i.e. with 2 searches). Then, skew and split move the children, so the reference should be valid. The only way I can see to do that with a search is with unsafe code: fn insert_or_update_with<'a, K: TotalOrd, V>(
node: &'a mut Option<~TreeNode<K, V>>,
key: K, value: V,
f: &fn(&K, &mut V)) -> &'a mut V {
match *node {
Some(ref mut save) => {
match key.cmp(&save.key) {
Less => {
let res: *mut V = unsafe {
transmute(insert_or_update_with(&mut save.left, key, value, f))
};
skew(save);
split(save);
unsafe{transmute(res)}
}
Greater => {
let res: *mut V = unsafe {
transmute(insert_or_update_with(&mut save.right, key, value, f))
};
skew(save);
split(save);
unsafe{transmute(res)}
}
Equal => {
save.key = key;
f(&save.key, &mut save.value);
&mut save.value
}
}
}
None => {
*node = Some(~TreeNode::new(key, value));
&mut node.get_mut_ref().value
}
}
} It compiles, but I didn't try running it and that's the first time I write unsafe code. And that's quite sad to have TreeMap using unsafe code. I hope I'm wrong and there is another solution. |
@TeXitoi I reached the same conclusion and was going to ask for a sanity check. I don't think doing 2 searches would help even if we wanted to sacrifice performance to write safe code. The key gets moved into the map and if you tried to keep a reference while you rebalanced the key, you'd run into exactly the same issue. My implementation uses |
That does indeed look hard to type check. It wasn't obvious to me from glancing at the code that it was safe amidst all the unique pointer juggling and so on. @davidhalperin I think doing an insert and then a search would work, if you wanted to keep the code safe? not sure why it matters that key/value are moved into the map. |
@nikomatsakis Let's say the helper Left => {
let k = find_or_insert_with(&mut save.left, key, f);
skew(save); // We can't borrow save again here because we're holding onto k
split(save);
k
} Is there a different way we could avoid do the insert then search strategy that would avoid that problem? |
@davidhalperin Ah, NOW I think I see your point. Yes, without the ability to clone the key, it does leave us in a bit of a pickle, doesn't it? You can't do the find after the insert because the key is moved; you can't return a pointer to the key because it would prolong the loan on the map (and rightly so). If were insistent on avoiding unsafe code, I imagine we could have some
Obviously this is a bit over the top, though out of idle curiosity I do wonder if you could encode the path in a u64 and a uint -- probably not, depends I guess on the balancing guarantees. :) |
cc me |
Is this solved? If not, I would like to work on it. |
@aochagavia My pull request got closed with the comment that the map trait should be thought out more, so I don't think this is going to be done as described in this issue (if it is, I should be able to dust of my changes pretty easily). If you want to work on something around this you should probably talk to the rust devs and see what they actually want. |
Nominating for removal from milestone. The world won't end if this method isn't defined in 1.0. |
Removing from milestone. (The process of reviewing the std lib and assigning stability attributes shouid eventually address this problem, perhaps by marking the existing |
Should this be closed now that rust-lang/rfcs#216 has been accepted? |
This isn't quite a dupe of that RFC because it doesn't mention the |
At very least, find_or_insert is deprecated, now. So adding it to Map is uh... dubious? |
…=flip1995 Rename lint `identity_conversion` to `useless_conversion` Lint name `identity_conversion` was misleading, so this PR renames it to `useless_conversion`. As decision has not really came up in the issue comments, this PR will probably need discussion. fixes rust-lang#3106 changelog: Rename lint `identity_conversion` to `useless_conversion`
No description provided.
The text was updated successfully, but these errors were encountered: