How to pass a HashMap to a function in Rust [duplicate] - hashmap

This question already has answers here:
What's the difference between placing "mut" before a variable name and after the ":"?
(4 answers)
Closed 6 years ago.
Can anybody explain why following code does not compile?
use std::collections::HashMap;
fn add(mut h: &HashMap<&str, &str>) {
h.insert("foo", "bar");
}
fn main() {
let mut h: HashMap<&str, &str> = HashMap::new();
add(&h);
println!("{:?}", h.get("foo"));
}
This is what rustc tells me
hashtest.rs:4:5: 4:6 error: cannot borrow immutable borrowed content `*h` as mutable
hashtest.rs:4 h.insert("foo", "bar");
^

The problem is that you pass a mutable reference to a HashMap (i.e. the reference can be changed to point to another HashMap), and not a reference to a mutable HashMap (i.e. the HashMap can change).
Here is a correct code:
use std::collections::HashMap;
fn add(h: &mut HashMap<&str, &str>) {
h.insert("foo", "bar");
}
fn main() {
let mut h: HashMap<&str, &str> = HashMap::new();
add(&mut h);
println!("{:?}", h.get("foo"));
}

Related

Mutably borrow a hash map inside a loop [duplicate]

This question already has answers here:
Why does this mutable borrow live beyond its scope?
(2 answers)
Closed 8 months ago.
I'd like to mutably borrow a hash map on every iteration of a loop.
I have the following hash map, function, and loop:
use std::collections::HashMap;
fn func<'a>(hash_map: &'a mut HashMap<&'a str, String>) {
unimplimented!();
}
fn loop() {
let mut hash_map = HashMap::new();
let mut i = 0;
while i < 10 {
func(&mut hash_map);
i += 1;
}
}
This will produce the following error on the func(&mut hash_map); line:
cannot borrow `hash_map` as mutable more than once at a time
`hash_map` was mutably borrowed here in the previous iteration of the looprustc(E0499)
main.rs(62, 25): `hash_map` was mutably borrowed here in the previous iteration of the loop
How can I refactor this to be able to mutably borrow the hash map on every iteration of the loop?
I believe I understand Rust's ownership rules enough to understand why this error is happening, just not well enough to fix it.
Note: I know there are better ways to write a loop in Rust, just wanted a very simple loop for this example.
Looks like I was using an unneeded lifetime in the function argument type definition. Instead of hash_map: &'a mut HashMap<&'a str, String>, I could just use hash_map: &mut HashMap<&'a str, String>.
The following code works for me.
use std::collections::HashMap;
use external::func;
fn func<'a>(hash_map: &mut HashMap<&'a str, String>) {
unimplimented!();
}
fn loop() {
let mut hash_map = HashMap::new();
let mut i = 0;
while i < 10 {
func(&mut hash_map);
i += 1;
}
}

Does a mutable String reference implement Copy [duplicate]

This question already has answers here:
Why is the mutable reference not moved here?
(4 answers)
Do mutable references have move semantics?
(1 answer)
Closed 1 year ago.
In the below code I was expecting the compiler to complain about use of moved value: xref on hello function's second call since mutable references do not implement Copy. The compiler doesn't raise any such error. What am I missing here?
fn main() {
let mut x: String = "Developer".to_string();
let x_ref: &mut String = &mut x;
hello(x_ref);
hello(x_ref);
}
fn hello(a: &mut String) {
println!("Hello {}", a);
}
Your example uses the mutable references after each other, which allows the compiler to perform an implicit reborrow. It basically turns this code into this:
hello(&mut *x_ref);
hello(&mut *x_ref);
Now you have two separate mutable borrows each only for the lifetime of the function call, thus they do not conflict with each other.
You see an error if you try to use it two times simultaneously.
fn main() {
let mut x: String = "Developer".to_string();
let x_ref: &mut String = &mut x;
hello(x_ref, x_ref);
}
fn hello(a: &mut String, b: &mut String) {
println!("Hello {} and {}", a, b);
}

Rust : insert uint in hashmap reference

I am new to Rust and I have this error at compilation time but I don't get it
error[E0614]: type `Option<u32>` cannot be dereferenced
--> src/main.rs:9:5
|
9 | *mymap.insert("hello world", 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Here is my code simplified to reproduce the issue:
use std::collections::HashMap;
fn main() {
let mymap: HashMap<&str, u32> = HashMap::new();
f(&mymap)
}
fn f(mymap: &HashMap<&str, u32>) {
*mymap.insert("hello world", 0);
}
Also the following does not work either
*mymap.insert("hello world", &0);
I don't find the root cause of my problem by googling it, I think I don't have the words. It looks like some borrowing issue.
You're actually not dereferencing mymap, you're actually dereferencing the result of insert(), because dereferencing (i.e. *) have a weaker precedence than a method call.
So it complains about dereferencing an Option<u32> because that's what insert() returns. If you actually wanted to dereference mymap you'd have to write (*mymap).insert("hello world", 0);. However, that is not needed in Rust.
If you remove the * then you will get a second problem, which is that you're attempting to mutate mymap, which is an immutable reference. So to be able to insert, i.e. mutate mymap in f, you need to pass it a mutable reference, i.e. mymap: &mut HashMap<&str, u32>.
use std::collections::HashMap;
fn main() {
let mut mymap: HashMap<&str, u32> = HashMap::new();
f(&mut mymap)
}
fn f(mymap: &mut HashMap<&str, u32>) {
mymap.insert("hello world", 0);
}
You don't need to dereference references on method calls, Rust will automatically do that for you. Also, you need to pass a mutable reference of mymap so you can actually perform the insert. Fixed example:
use std::collections::HashMap;
fn main() {
let mut mymap: HashMap<&str, u32> = HashMap::new();
f(&mut mymap)
}
fn f(mymap: &mut HashMap<&str, u32>) {
mymap.insert("hello world", 0);
}
playground

How to rereference a mutable slice [duplicate]

This question already has answers here:
Can I reassign a mutable slice reference to a sub-slice of itself?
(2 answers)
Closed 2 years ago.
I want to uptade a slice through a mutable reference.
While this does work with immutable slices:
fn shrink(value: &mut &[u8]) {
*value = &value[0..2];
}
fn main() {
let a = [0; 4];
let mut a_slice: &[u8] = &a;
shrink(&mut a_slice);
println!("{:?}", a_slice);
}
It doesn't work with mutable ones:
fn shrink<'a: 'b, 'b>(value: &'a mut &'b mut [u8]) {
*value = &mut value[0..2];
}
fn main() {
let mut a = [0; 4];
let mut a_slice: &mut [u8] = &mut a;
shrink(&mut a_slice);
println!("{:?}", a_slice);
}
Error message:
error[E0502]: cannot borrow `a_slice` as immutable because it is also borrowed as mutable
--> src/main.rs:8:22
|
7 | shrink(&mut a_slice);
| ------------ mutable borrow occurs here
8 | println!("{:?}", a_slice);
| ^^^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
I know that there is a way to update the slice by directly returning a subslice.
But is there a way to make rereferencing a mutable slice through mutable reference possible?
The problem is similar to this one, but I can't figure what makes it so different, that proposed solution doesn't work.
I don't know what the problem is with that code, but one option would be to return the updated slice directly:
fn shrink(value: &mut [u8]) -> &mut [u8] {
&mut value[0..2]
}
fn main() {
let mut a = [0; 4];
let mut a_slice = &mut a[..];
a_slice = shrink(a_slice);
println!("{:?}", a_slice);
}
Rather than updating via the mutable reference, updating in the caller makes it clear that the old value of a_slice won't be used any more.

rust: expected lifetime parameter problem [duplicate]

This question already has answers here:
How to return new data from a function as a reference without borrow checker issues?
(1 answer)
Return local String as a slice (&str)
(7 answers)
Closed 3 years ago.
I am new to Rust and was making a simple program to practice which takes 2 numbers and prints the numbers between them. This is my code
fn main() {
let a: u32 = 2;
let b: u32 = 10;
let a = result(&a, &b);
println!("{:?}", a);
}
fn result(a: &u32, b: &u32) -> [Vec<&u32>] {
let mut vec = Vec::new();
for x in a..b {
vec.push(a);
}
vec
}
When i run this program, i get this error
fn result(a: &u32, b: &u32) -> [Vec<&u32>] {
| ^ expected lifetime parameter
The concepts of borrowing and lifetimes are still very new and strange to me. Please help me in determining where i am wrong.
The error message is quite clear here:
this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from a or b
Providing an explicit lifetime would help the compiler understand what you're trying to do:
fn result<'a>(a: &'a u32, b: &'a u32) -> Vec<&'a u32> {
let mut vec: Vec<&'a u32> = Vec::new();
for x in *a..*b {
vec.push(&x);
}
vec
}
But the above wouldn't work either, as borrowing x results in borrowing a variable whch only lives in the scope a single iteration:
vec.push(&x);
^^ borrowed value does not live long enough
What you probably want is to avoid borrowing altogether:
fn result(a: u32, b: u32) -> Vec<u32> {
let mut vec = Vec::new();
for x in a..b {
vec.push(x);
}
vec
}
live example on godbolt.org

Resources