rustcollectionsiteratorset-intersection

Intersection of two BTreeSet objects in Rust


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.)


Solution

  • 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();
    

    How it works:

    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...