I can't figure out how to take two BTreeSet objects and create a new, owned, BTreeSet from the intersection operation.
Here is a Minimal Example:
use std::collections::BTreeSet;
fn test() -> BTreeSet<u64> {
let mut s1 = BTreeSet::new();
let mut s2 = BTreeSet::new();
s1.insert(1u64);
s2.insert(2u64);
let s_out = s1.intersection(&s2);
return s_out; // this does not work
}
The reason this does not work appears to be because intersection
creates an iterator, which is lazy evaluated. I want to create a new "owned" object / BTreeSet from the existing two BTreeSets.
How do I do that?
intersection
returns some other kind of object which is an Intersection
object. The intended purpose is presumably so that it can be lazy-evaluated. (See docs.)
The solution is fairly trivial and requires this. The type hints are optional.
let s_out = s1.intersection(&s2);
s_out.cloned().collect::<BTreeSet<u64>>();
or
let s_out = s1.intersection(&s2);
s_out.cloned().collect();
s_out
is an iterator type. It provides lazy-evaluation. What this means is that s_out
is not another BTreeSet
. It does not have the ownership semantics which I intended.
As described in the Question, what I wanted to do was produce a new, owned, BTreeSet
.
In order to achieve this, we have to call collect
on the iterator. That will iterate over all the elements, and "collect" them into a new std::collection
type. In this case I explicitly specified BTreeSet
, but that may not be required if the type can be inferred from elsewhere in the code...
The reason cloned
is required is otherwise we obtain a BTreeSet of references to existing things, rather than "owned" clones of those things.
How exactly ownership behaves is dependent on what types you are working with and whether Copy
or Clone
are derived for those types.
At this point, the answer becomes a discussion or Rust ownership semantics, so the reader is encouraged to find references for this elsewhere...