【问题标题】:Assign value from match statement从匹配语句中赋值
【发布时间】:2016-04-16 19:59:19
【问题描述】:

我正在尝试在 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 范围的长度内有效,但是如何从必须调用另一个函数的匹配语句中返回值?

【问题讨论】:

    标签: rust


    【解决方案1】:

    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!"),
        }
    };
    

    【讨论】:

      【解决方案2】:

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

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

      【讨论】:

        【解决方案3】:

        有一个相当简单的技巧:增加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 只在必要时使用,并且不需要更改程序中的类型。

        注意:我在.to_str() 之后添加了一个.unwrap(),因为.to_str() 返回一个Option。请注意,它返回 Option&lt;&amp;str&gt; 的原因是因为并非所有路径都是有效的 UTF-8 序列。你可能想坚持Path/PathBuf

        【讨论】:

        • 我确实最终将字符串转换为 PathBuf 对象,以便我可以按照您的建议修改路径。
        猜你喜欢
        • 2011-10-24
        • 1970-01-01
        • 2011-10-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-01-02
        • 2015-07-15
        • 1970-01-01
        相关资源
        最近更新 更多