简体   繁体   English

是否可以在模式中创建可变引用的可变值?

[英]Is it possible to create a mutable value of a mutable reference in a pattern?

When pattern-matching, you can specify that you'd like to get a mutable reference to the contained value by using ref mut :在模式匹配时,您可以使用ref mut指定您想要获取对所包含值的可变引用:

let mut score = Some(42);
if let Some(ref mut s) = score {
    &mut s;
}

However, the inner value is not mutable:但是,内部值是不可变的:

error[E0596]: cannot borrow immutable local variable `s` as mutable
 --> src/main.rs:4:14
  |
4 |         &mut s;
  |              ^
  |              |
  |              cannot reborrow mutably
  |              try removing `&mut` here

I tried to add in another mut , but that was not valid:我尝试添加另一个mut ,但这无效:

if let Some(mut ref mut s) = score {
    &mut s;
}
error: the order of `mut` and `ref` is incorrect
 --> src/main.rs:3:17
  |
3 |     if let Some(mut ref mut s) = score {
  |                 ^^^^^^^ help: try switching the order: `ref mut`

error: expected identifier, found keyword `mut`
 --> src/main.rs:3:25
  |
3 |     if let Some(mut ref mut s) = score {
  |                         ^^^ expected identifier, found keyword

error: expected one of `)`, `,`, or `@`, found `s`
 --> src/main.rs:3:29
  |
3 |     if let Some(mut ref mut s) = score {
  |                             ^ expected one of `)`, `,`, or `@` here

Not a direct answer, but possible workarounds不是直接的答案,而是可能的解决方法

Create an intermediate variable创建中间变量

if let Some(ref mut s) = score {
    let mut s = s;
    &mut s;
}
#[derive(Debug)]
struct X;

enum Foo<T> {
    Bar(T),
    _Baz,
}

fn main() {
    let mut score = Foo::Bar(X);

    if let Foo::Bar(ref mut s) = score {
        //let x = s;
        //println!("{:?}", **x); ! not possible
        let x = &mut &mut *s; // &mut &mut X
        println!("{:?}", **x);
    }
}

For Option specifically专为Option

if let Some(ref mut s) = score.as_mut() {
    s; //:&mut &mut i32
}
if let Some(mut s) = score.as_mut() {
    &mut s;
}

Below code may give an idea for the possible solution to the problem.下面的代码可能会为问题的可能解决方案提供一个想法。 It's just a sample & testable code to provide a tiny example that aimed at the issue.这只是一个示例和可测试的代码,用于提供一个针对该问题的小示例。 Of course it may not cover the whole intents and purposes.当然,它可能无法涵盖全部意图和目的。

fn main() {
    let mut score = Some(42i32);

    let res = if let Some(41) = score {
        println!("41 is matched");
        1i32
    } else if let Some(ref mut s) = score { //&mut score {
        //let mut s2 = s;
        //println!("s: {:#?}", s);
        test(&mut &mut *s); // This part may be like this for borrowing
        //println!("s: {:#?}", s);
        1i32
    } else {
        0i32
    };

    //println!("Result: {:#?}", score);
    assert_eq!(res, 1i32);
}

fn test(ref mut s: &mut &mut i32) -> i32 {
    //let mut s2 = s;
    return test2(&mut *s);
}

fn test2(n: &mut i32) -> i32 {
    *n += 1;
    //println!("Value: {}", *(*n));
    return *n;
}

Live Version: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7c3e7e1ee712a31f74b201149365035f直播版本: https : //play.rust-lang.org/? version =stable&mode=debug&edition=2018&gist=7c3e7e1ee712a31f74b201149365035f

Gist Link: https://gist.github.com/7c3e7e1ee712a31f74b201149365035f要点链接: https : //gist.github.com/7c3e7e1ee712a31f74b201149365035f

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM