Conversation
This comment has been minimized.
This comment has been minimized.
… block in append_with()
This comment has been minimized.
This comment has been minimized.
|
Marked as waiting on ACP. |
…rified doc comments
|
@rustbot label -S-waiting-on-review Implemented the ACP changes with renaming function, changing signature, and changed the doc comments for merge a bit (it's similar to |
|
Oops, I think it's: |
This comment has been minimized.
This comment has been minimized.
|
I don't think the CI issue is coming from my end since it's saying spurious network error? |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
3453de7 to
1b29082
Compare
|
Stepping off rotation for a bit. @rustbot reroll |
|
@rustbot ready |
|
Note: I have a different implementation of I think I'll put the optimized version in a separate PR because I know that this PR's code is safe (or safer) due to the implementation being a mirror of Let me know if this sounds good to you. |
| let mut b = BTreeMap::new(); | ||
| for i in 5..$len { | ||
| b.insert(i, 2 * i); | ||
| } |
There was a problem hiding this comment.
Can we add some comments on why certain constants were chosen here or what the intent of this code is? E.g., 5..$len is not immediately apparent when reading this to me.
There was a problem hiding this comment.
In the new PR, I mentioned a comment above macro_rules! create_merge_test {...} saying:
// On merging keys 5..8, the values are
// added together (i + 2 * i)| lhs.insert(IdBased { id: 0, name: "lhs_k".to_string() }, "1".to_string()); | ||
| rhs.insert(IdBased { id: 0, name: "rhs_k".to_string() }, "2".to_string()); | ||
|
|
||
| lhs.merge(rhs, |_, mut lhs_val, rhs_val| { |
There was a problem hiding this comment.
Can we add a test / extend this one to verify that lhs_val and rhs_val are from left/right respectively?
There was a problem hiding this comment.
I hope I'm understanding correctly, but do you want me to add assertion cases in this merge callback function that verifies that lhs_val == "1", and rhs_val == "2"?
I could do that.
| @@ -33,6 +33,36 @@ impl<K, V> Root<K, V> { | |||
| self.bulk_push(iter, length, alloc) | |||
| } | |||
|
|
|||
| /// Merges all key-value pairs from the union of two ascending iterators, | |||
| /// incrementing a `length` variable along the way. The latter makes it | |||
| /// easier for the caller to avoid a leak when a drop handler panicks. | |||
There was a problem hiding this comment.
| /// easier for the caller to avoid a leak when a drop handler panicks. | |
| /// easier for the caller to avoid a leak when a drop handler panics. |
There was a problem hiding this comment.
In the new PR, I use CursorMut to help me merge the keys from other BTreeMap into self BTreeMap, so I don't have to consume the self BTreeMap reconstruct the merged BTreeMap from scratch.
| /// If you want the tree to end up in a strictly ascending order, like for | ||
| /// a `BTreeMap`, both iterators should produce keys in strictly ascending | ||
| /// order, each greater than all keys in the tree, including any keys | ||
| /// already in the tree upon entry. |
There was a problem hiding this comment.
When we say "including any keys already in the tree", what keys are not in that set but relevant here?
There was a problem hiding this comment.
I copied the comment from the merge_from_sorted_iters function above, only making changes to the second paragraph I believe. However, looking at this comment, it's kinda already implied that a valid BTreeMap will be in strictly ascending/descending order if both BTreeMap follow the rule that their keys are in ascending/descending order. Not sure what the comment was getting at it here "including any keys already in the tree upon entry"
|
|
||
| let self_iter = mem::replace(self, Self::new_in((*self.alloc).clone())).into_iter(); | ||
| let other_iter = mem::replace(&mut other, Self::new_in((*self.alloc).clone())).into_iter(); | ||
| let root = self.root.get_or_insert_with(|| Root::new((*self.alloc).clone())); |
There was a problem hiding this comment.
Why is this get_or_insert_with? Isn't the root guaranteed to be absent after the replace with a new tree above?
There was a problem hiding this comment.
To be honest with you, I copied the code verbatim from BTreeMap::append(), which does this as well. The root does look to be absent though since we mem::replace() self with Self::new_in((*self.alloc).clone()).
The new PR doesn't use this approach though and preserves the content of self BTreeMap and inserting the other BTreeMap items in the right spots using CursorMut
|
Reminder, once the PR becomes ready for a review, use |
|
@Mark-Simulacrum this PR will be closed in favor of #152418. I appreciate your time looking into this PR though! |
This PR implements
BTreeMap::append_with()as mentioned in #147700 (and discussed by the forum post linked in the issue). I'm not sure if the issue made is an approval for this feature, but regardless I'm going to make an ACP soon. I decided to made a small change to the API forappend_withthan the one proposed by @nagisa:I think having the
conflictfunction ownself's value and returning an owned value might give a lot more flexibility to the user. It also feels a bit more intuitive to me as the user that a value of typeVis being put intoselfwhen there's conflicting keys betweenselfandother.For example, if my values are
Stringtypes and I want to combine my values when keys are conflicting, then they can either mutateselfs value with.push_str()passing inother's value and returnself's value, or they can useformat!()to return a concatenation ofself's andother's value.Now, a consequence for this approach is that it's very well possible that the user decides to return a value
Vthat has nothing to do withselforotherwhen it comes to a conflicting key. However, should we decide to doconflict: impl FnMut(&K, &mut V, V), I could have mutatedself's value easily to produce a whole different value that has nothing to do with the original value ofselforother.