简体   繁体   中英

How do you borrow a mutable reference during a match?

I found this but could not get my code to work. I still have the sneaking suspicion that I need ref somehow.

I am trying to make a reasonable Table class in Rust to learn more about the language and running into some trouble with understanding the borrow checker and mutability concepts as well as their corresponding syntax.

I want the table class to be flexible and allow for different column types where the data types within the columns are homogeneous. So, a column of ints, floats, strings etc.


I started without flexible data types and came up with this hashmap mapping ints (the column labels in this case) to vectors of ints (the data within the columns).

use std::collections::HashMap; 

fn main() {
    let mut d: HashMap<isize, Vec<isize>> = HashMap::new();
    d.insert(0, Vec::new());
    d.get_mut(&0).unwrap().push(0); 

    println!("{:?}", d);
    // nice {0: [0]}
}

To implement flexible data types, enum seemed like a decent start so that is where I started but I am stuck on the implementation.

use std::collections::HashMap; 

#[derive(Debug)] 
enum VT {
    A(Vec<isize>),
    B(Vec<f64>),
}

fn main() {
    let mut d: HashMap<isize, VT> = HashMap::new();
    d.insert(0, VT::A(Vec::new()));

    match d.get_mut(&0).unwrap() {
        &mut VT::A(v) => v.push(0),
        &mut VT::B(v) => v.push(0.1), // would not be reached as-is 
    } 

    println!("{:?}", d);
}
// cannot borrow immutable local variable `v` as mutable :(

Ultimately, having a library similar to pandas would be the dream. For now, implementing a table is good Rust practice.

Before Rust 1.26 (from mid-2018, so any readers now are probably using a newer version), write your match block like one of these two:

match d.get_mut(&0).unwrap() {
    &mut VT::A(ref mut v) => v.push(0),
    &mut VT::B(ref mut v) => v.push(0.1),
}
match *d.get_mut(&0).unwrap() {
    VT::A(ref mut v) => v.push(0),
    VT::B(ref mut v) => v.push(0.1),
}

In patterns ref mut takes a mutable reference, even as &mut dereferences a mutable reference.

(The generally preferred convention was match *foo { X => … } rather than match foo { &mut X => … } , due to less noise on the more numerous match branch lines, but it flipped the other way after the Rust 1.26 changes, since now that has less noise associated with it.)


From Rust 1.26 onwards , any & / ref and &mut / ref mut pairs can be omitted, with the compiler inferring them. (This is a slightly simplistic explanation, but it's the essence of it.)

match d.get_mut(&0).unwrap() {
    VT::A(v) => v.push(0),
    VT::B(v) => v.push(0.1),
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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