Dan
Dan

Reputation: 5313

How can I have a function argument that takes an iterator with items that are owned and ones that are borrowed?

I would like to do the following and allow my perform function to take an iterator with &usize or with usize items as below.

fn perform<'a, I>(values: I) -> usize
where
    I: Iterator<Item = &'a usize>,
{
    *values.max().unwrap()
}

fn main() {
    let v: Vec<usize> = vec![1, 2, 3, 4];

    // Works.
    let result = perform(v.iter());
    print!("Result: {}", result);
    
    // Does not work: `expected `&usize`, found `usize``.
    let result = perform(v.iter().map(|v| v * 2));
    print!("Result again: {}", result)
}

Playground example here.

Upvotes: 1

Views: 35

Answers (2)

Another way may be accepting owned values in perform like this:

fn perform<I>(values: I) -> usize
where
    I: Iterator<Item = usize>,
{
    values.max().unwrap()
}

fn main() {
    let v: Vec<usize> = vec![1, 2, 3, 4];

    // Works.
    let result = perform(v.iter().map(|x| *x));
    print!("Result: {}", result);

    // Does not work: `expected `&usize`, found `usize``.
    let result = perform(v.iter().map(|v| v * 2));
    print!("Result again: {}", result)
}

Upvotes: 2

Silvio Mayolo
Silvio Mayolo

Reputation: 70267

In this case, by making your function more polymorphic, we actually get the behavior for free. Your perform works for any Ord value.

fn perform<'a, I, T>(values: I) -> T
where
    I: Iterator<Item = T>,
    T: Ord,
{
    values.max().unwrap()
}

Now usize is Ord and so is &usize (by a blanket impl that makes references to any orderable type orderable).

Upvotes: 3

Related Questions