简体   繁体   中英

How do I apply an explicit lifetime bound to a returned trait?

Returning an iterator from a function in Rust is an exercise of Sisyphean dimensions, but I am told it's possible to return one as a trait without quite so much pain. Unfortunately, it isn't working: apparently, I need an explicit lifetime bound? Which is apparently not the same thing as adding a lifetime parameter. Which means I have no idea how to do that.

Here's my (tiny, test) code:

fn main() {
    let args = get_args();

    for arg in args {
        println!("{}", arg);
    }
}

fn get_args() -> Iterator {
    std::env::args().filter_map(|arg| arg.into_string().ok())
}

What is the appropriate way to make this actually work ?

Edit: rust version rustc 1.0.0-nightly (00df3251f 2015-02-08 23:24:33 +0000)

You can't return a bare Iterator from a function, because it is a trait, thus not a sized type.

In your situation, you'll need to put the iterator object inside a box, in order to make it into a sized object that can be returned from the function.

To do so, you can change your code like this:

fn get_args() -> Box<Iterator<Item=String> + 'static> {
    Box::new(std::env::args().filter_map(|arg| arg.into_string().ok()))
}

Here I've added a lifetime specifier 'static for the trait object, meaning that it is completely self-owned (a function taking no arguments will almost always return something valid for the 'static lifetime in this sense).

You also need the <Item=String> part to explicit the type of data yielded by your iterator. In this case: Strings.

In this specific case you can manage to return a concrete type from your get_args, like so:

fn get_args() -> FilterMap<Args, fn(OsString) -> Option<String>> {
    fn arg_into_string(arg: OsString) -> Option<String> { arg.into_string().ok() }
    args().filter_map(arg_into_string as fn(OsString) -> Option<String>)
}

basically this applies to all the cases where the closure you use in the iterator adapter (in your case filter_map) is not really a closure, in that it does not capture any environment, and it can be modeled by a plain old function.

In general, if you do need to return a type that does contain a closure, you will indeed need to box it and return a trait object. In your case:

fn get_args() -> Box<Iterator<Item=String> + 'static> {
    Box::new(std::env::args().filter_map(|arg| arg.into_string().ok()))
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM