从匹配语句中分配值

时间:2016-04-16 19:59:20

标签: rust

我正在尝试在Rust中创建一个Git命令。我正在使用clap参数解析器包进行命令行处理。我希望我的命令为可以使用的目录取一个可选参数。如果命令没有收到选项,它会假定用户主目录。

我知道我可以使用std::env::home_dir函数获取用户的主目录(如果已设置)但是让我困惑的部分是如何正确使用match运算符来获取值的路径。这是我一直在尝试的:

use std::env;

fn main() {
    // Do some argument parsing stuff...

    let some_dir = if matches.is_present("some_dir") {
        matches.value_of("some_dir").unwrap()
    } else {
        match env::home_dir() {
            Some(path) => path.to_str(),
            None       => panic!("Uh, oh!"),
        }
    };

    // Do more things

当我尝试编译时,我收到一条错误消息,说path.to_str()的活动时间不够长。我知道to_str返回的值是match范围的长度,但是如何从必须调用另一个函数的匹配语句中返回一个值?

3 个答案:

答案 0 :(得分:2)

path.to_str()将返回对&str中包含的内部字符串的path引用,该内部字符串的有效期仅为path,位于match内手臂 您可以使用to_owned获取该&str的拥有副本。您必须相应地调整clap的值,使其在if的两个分支中具有相同的类型:

let some_dir = if matches.is_present("some_dir") {
    matches.value_of("some_dir").unwrap().to_owned()
} else {
    match env::home_dir() {
        Some(path) => path.to_str().unwrap().to_owned(),
        None       => panic!("Uh, oh!"),
    }
};

或者,您可以使用Cow来避免第一个分支中的副本:

use std::borrow::Cow;

let some_dir: Cow<str> = if matches.is_present("some_dir") {
    matches.value_of("some_dir").unwrap().into()
} else {
    match env::home_dir() {
        Some(path) => path.to_str().unwrap().to_owned().into(),
        None       => panic!("Uh, oh!"),
    }
};

答案 1 :(得分:1)

正在发生的事情是match语句的范围取得PathBuf返回的env::home_dir()对象的所有权。然后,您尝试返回对该对象的引用,但该对象不再立即存在。

解决方案是返回PathBuf而不是对它的引用(或将其转换为String并返回它,而在任何情况下,它必须是拥有数据的某种类型)。您可能必须更改matches.value_of("some_dir").unwrap()返回的内容,以便两个分支返回相同的类型。

答案 2 :(得分:1)

有一个相当简单的技巧:增加path的范围(以及它的生命周期),以便你可以参考它。

use std::env;

fn main() {
    // Do some argument parsing stuff...

    let path; // <--

    let some_dir = if matches.is_present("some_dir") {
        matches.value_of("some_dir").unwrap()
    } else {
        match env::home_dir() {
            Some(p)    => { path = p; path.to_str().unwrap() },
            None       => panic!("Uh, oh!"),
        }
    };

    // Do more things
}

效率很高,因为path仅在必要时使用,并且不需要更改程序中的类型。

注意:我在.unwrap()之后添加了.to_str(),因为.to_str()会返回Option。请注意它返回Option<&str>的原因是因为并非所有路径都是有效的UTF-8序列。您可能希望坚持Path / PathBuf