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.
First, we change s to be mut . Then we create a mutable reference with &mut s where we call the change function, and update the function signature to accept a mutable reference with some_string: &mut String . This makes it very clear that the change function will mutate the value it borrows.
Back to Rust. A mutable reference is a borrow to any type mut T , allowing mutation of T through that reference. The below code illustrates the example of a mutable variable and then mutating its value through a mutable reference ref_i .
Rust supports a concept, borrowing, where the ownership of a value is transferred temporarily to an entity and then returned to the original owner entity.
A reference represents a borrow of some owned value. You can get one by using the & or &mut operators on a value, or by using a ref or ref mut pattern. For those familiar with pointers, a reference is just a pointer that is assumed to not be null.
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),
}
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With