How do you borrow a mutable reference during a mat

2020-08-17 07:55发布

问题:

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.

回答1:

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),
}


标签: rust