如何匹配Arc内的选项?

时间:2018-01-27 01:03:39

标签: rust

docs for Arc<T>说:

  

Arc<T>会自动解除引用T(通过Deref特征),因此您可以在{{1}类型的值上调用T方法}}

但有没有办法允许匹配Arc<T> - 类型?

这是一个简单的例子:

Option

编译错误是:

use std::sync::Arc;

fn main() {
    let foo: Arc<Option<String>> = Arc::new(Some("hello".to_string()));

    if foo.is_some() {
        println!("{}", foo.unwrap());
    }

    match foo {
        Some(hello) => {
            println!("{}", hello);
        }
        None => {}
    }
}

2 个答案:

答案 0 :(得分:6)

不,您无法匹配Option内的Arc。要在模式匹配中使用类型,必须可以使用该类型的实现,但Arc的实现不公开。

在某些情况下,您可以执行某种转换,以便能够匹配参考

例如,由于Arc<T>实现了Deref,您可以使用*运算符通过Arc<T>取消引用基础T。由于这种匹配有some ergonomic syntax,因此您可以在Option内对值进行引用,而无需获取所有权:

match *foo {
    Some(ref hello) => {
        println!("{}", hello);
    }
    None => {}
}

您还可以使用Option::as_ref&Option<T>automatically dereferencedArc<T>转换为Deref)转换为Option<&T>

match Option::as_ref(&foo) {
    Some(hello) => {
        println!("{}", hello);
    }
    None => {}
}

不幸的是,您不能只调用.as_ref(),因为特征方法AsRef::as_ref优先。

在这两种情况下,如果您只关心其中一个匹配组,那么使用if let会更加惯用:

if let Some(ref hello) = *foo {
    println!("{}", hello);
}

答案 1 :(得分:3)

第一个println通过了编译器的早期阶段,但它在稍后阶段被借用检查程序标记。第二个println更容易解决。

use std::sync::Arc;

fn main() {
    let foo: Arc<Option<String>> = Arc::new(Some("hello".to_string()));

    if foo.is_some() {
        let f1: &Option<String> = foo.as_ref();
        let f2: Option<&String> = f1.as_ref();
        let f3: &String = f2.unwrap();
        println!("{}", f3);

        println!("{}", foo.as_ref().as_ref().unwrap())
    }

    match *foo {
        Some(ref hello) => {
            println!("{}", hello);
        }
        None => {}
    }
}

第一个println令人困惑地使用了两个as_ref()方法调用。第一个as_refArc采取行动,类型为签名Fn(&Arc<Option<String>>) -> &Option<String>。第二个作用于Option,类型为签名Fn(&Option<String>) -> Option<&String>

playground