在借用的上下文中引用选项

时间:2016-03-14 14:55:45

标签: rust

我希望能够在借来的上下文中打开一个可选项。例如,println!某个值:

struct Optional {
    v: Option<String>,
    v2: Option<String>,
}

fn main() {
    let mut optionals = vec![];
    optionals.push(Optional { v: Some("foo".to_string()), v2: Some("bar".to_string())});
    optionals.push(Optional { v: None, v2: None });

    for optional in &optionals {
        println!("v:{} v2:{}", optional.v.unwrap_or("none".to_string()), optional.v2.unwrap_or("none".to_string()));
    }
}

我的理解是,这是不可能的,因为借用了optionalunwrap_or消费了它的输入,这是因为它被借用而被禁止。我尝试将ref带到结构值但又失败了,如何在不消耗optionals的情况下实现我想要的目标。

1 个答案:

答案 0 :(得分:3)

使用Option::as_ref。在您的示例中,您还必须处理需要将&String的类型与默认值匹配的事实。

let v = optional.v.as_ref().map(|s| s as &str).unwrap_or("none");
let v2 = optional.v2.as_ref().map(|s| s as &str).unwrap_or("none");
println!("v:{} v2:{}", v, v2);

作为ker points out,您还可以映射AsRef::as_ref

let v = optional.v.as_ref().map(AsRef::as_ref).unwrap_or("none");
let v2 = optional.v2.as_ref().map(AsRef::as_ref).unwrap_or("none");
println!("v:{} v2:{}", v, v2);

作为qthree points out.map().unwrap()的版本较短。像Rust Clippy这样的工具可以帮助您找到这些工具,当您没有一大批优秀的程序员查看您的代码时; - ):

let v = optional.v.as_ref().map_or("none", |s| s as &str);
let v2 = optional.v2.as_ref().map_or("none", AsRef::as_ref);
println!("v:{} v2:{}", v, v2);
  

这是在借用的上下文中打印可选项的最惯用的方法吗?

这是值得商榷的。例如,如果打印的值为"none",那么读者无法知道它实际上是Some("none")还是None。这种区别对您的代码的操作有影响吗?

如果我要将数据打印到终端以供程序员使用,我更有可能只使用Debug格式化程序进行打印:

println!("v:{:?} v2:{:?}", optional.v, optional.v2);

虽然我真的只为Debug派生Optional并打印整件事:

#[derive(Debug)]
struct Optional { ... }
for optional in &optionals {
    println!("{:?}", optional);
}

如果真的是供用户使用,我可能会有不同的短语:

match optional.v {
    Some(ref s) => println!("The value is: {}", s),
    None => println!("The value is not set"),
};