Does not live long enough


#1

Hello i try create utils for get args from cli. It’s ok then use to_owned, but i understund this make copy and it’s bad, but when i use just func i get live time error. Whats practic good?

extern crate clap;
use clap::{Arg, App, SubCommand};


pub struct RunArgs {
    pub input: String,
    pub output: String,
    pub path: String
}

pub fn get_args() -> RunArgs {
    let matches = App::new("***")
        .version("0.1.0")
        .author("Sergey Emelyanov ***")
        .about("This application help create Python or ReactJS files from templates")
        .arg(Arg::with_name("input")
            .short("i")
            .long("input")
            .help("Sets the input file to use, format .yml")
            .takes_value(true))
        .arg(Arg::with_name("output")
            .short("o")
            .long("output")
            .help("Sets the output path where save result")
            .takes_value(true))
        .arg(Arg::with_name("path")
            .short("p")
            .long("path")
            .help("Sets the path where stored templates")
            .takes_value(true))
        .get_matches();

    let input= matches
        .value_of("input")
        .unwrap_or("./some.yml")
        .to_owned();

    let output= matches
        .value_of("output")
        .unwrap_or(".")
        .to_owned();

    let path= matches
        .value_of("oath")
        .unwrap_or("~/some.yml")
        .to_owned();

    RunArgs { input, output, path }
}

#2

Unnecessary copies which are done frequently is typically not great for performance, but a once-off copy you do at the beginning of your program is perfectly fine.

Arguably it actually makes everything else simpler because anything using those arguments is now no longer bound to the lifetime of your argument parser. In this case you actually need to make the copy because the string you get from the argument parser is tied to a local variable in the argument parsing function. If you didn’t use to_owned() then you’d get a compile error because you’ve effectively got a dangling pointer.

TL;DR: Avoiding all copies ever is probably premature optimisation. Use references where you can, but if you need to do a copy every now and then, that’s okay too. 99.99% of the time this will have a negligible impact on the performance of your application.


#3

You can never return a reference to something created inside a function. A function can only return a reference to something created outside of it.

If you really want just references, instead of get_matches use get_matches_from and pass args to the function, so that clap can then return references to the args that outlive the function.

https://play.rust-lang.org/?gist=bc4932811518f05ad5c54fe9ac01f739&version=stable

However, note that this whole thing will make your program only about 200 nanoseconds faster.


#4

Thanks all, can i say what i need read about live time and borrowed or get practice, i read rust book and example rust but not undertand all concepts?


#5

The best way to learn about lifetimes is by practicing. In your normal projects just try to use references more often when you might otherwise make a copy, then see what happens.

Rust traditionally has very good error messages, so if you have any lifetime errors then the compiler will normally help you figure it out. Otherwise if you’ve been sitting there trying to reason about a lifetime error for ages, chuck a cut down version in the playpen and ask around on this forum or Reddit. People are usually very happy to help and it’ll also serve as a resource for other people encountering similar issues :slight_smile:


#6

In this case how i can send &str to my func and set from matches?