#Iterator over references as input parameter with owned value as return value

5 messages · Page 1 of 1 (latest)

amber needle
#

Is it possible to remove lifetime parameter <'a> from signature of function where lifetime is used for Iterator<Item = 'a u8> in function which return owned value? Example of such function is

fn build_string<'a, I>(iter: &mut I) -> String
where
    I: Iterator<Item = &'a u8>,
{
    match iter.next() {
        Some(x) => format!("Value is {x}"),
        None => "No value".to_owned(),
    }
}

According my current (pure) knowledge is rust is lifetime parameter 'a in <'a, I> unnecessary, because this function build owned value with lifetime independent on iterator.

queen kettle
# amber needle Is it possible to remove lifetime parameter <'a> from signature of function wher...

Short answer: No, you need 'a here.
Longer answer: If you write it using argument-position-impl Trait instead of a generic, then there is an unstable feature you can enable to not need 'a: ```rs
#![feature(anonymous_lifetime_in_impl_trait)]
fn build_string(iter: &mut impl Iterator<Item = &u8>) -> String {
match iter.next() {
Some(x) => format!("Value is {x}"),
None => "No value".to_owned(),
}
}


Longer answer: For this specific example, where the referent type is `Copy` and small, you should use `Iterator<Item = u8>` instead of `Iterator<Item = &u8>`, and just have callers pass in `their_iter.copied()` instead of `their_iter` ```rs
fn build_string(iter: &mut impl Iterator<Item = u8>) -> String {
    match iter.next() {
        Some(x) => format!("Value is {x}"),
        None => "No value".to_owned(),
    }
}
#

Also: either way, consider allowing the iterator to be Iterator<...> + ?Sized so users can pass in &mut dyn Iterator<Item = ...>, e.g. ```rs
fn build_string<'a, I>(iter: &mut I) -> String
where
I: Iterator<Item = &'a u8> + ?Sized,
{ ... }
fn build_string2(iter: &mut (impl Iterator<Item = u8> + ?Sized)) -> String {
...
}


Or, just take the iterator by value (`&mut I` implements `Iterator` when `I` does, so users can still pass in a borrowed iterator) ```rs
fn build_string<'a, I>(mut iter: I) -> String
where
    I: Iterator<Item = &'a u8>,
{ ... }
fn build_string2(mut iter: impl Iterator<Item = u8>) -> String {
    ...
}
amber needle
#

Thank you @queen kettle for your reply and confirmation that it is not possible to remove this lifetime. I appreciate it.

Only for information:

  • second example - I can not use this because data will be big
  • third exmpale - if I understand this correctly, in current situtation I allowe only known types in compile time and with your duggestion if allow also dyn?
  • fourth example - I can not do it because for next call it can be called differend function which take iterrator passed to build_string
queen kettle
# amber needle Thank you <@270963063816060928> for your reply and confirmation that it is not ...

if I understand this correctly, in current situtation I allowe only known types in compile time and with your duggestion if allow also dyn?
In the currentl situation, you only allow Sized iterator types (they can be a generic though, they don't have to be known concretely in the code calling build_string), whereas with the + ?Sized, you also allow unsized iterator types, basically the only one of which you'll ever encounter is dyn Iterator<Item = ...>, yes