I have the following struct Grid where I would like to have a mutable get function which returns mutable references to the underlying Cells:
MWE here
struct Cell {
c: i64,
}
struct Grid {
a: [Cell; 3],
}
impl Grid {
fn cell_i(&mut self, i: usize) -> &mut Cell {
return &mut self.a[i];
}
fn neighbors(&mut self, _i: usize) -> (&mut Cell, &mut Cell) {
return (self.cell_i(0), self.cell_i(2));
}
}
fn main() {
let a = &mut Grid {
a: [Cell { c: 3 }, Cell { c: 4 }, Cell { c: 5 }],
};
let _bs = a.neighbors(1);
}
I am just puzzeled as a beginner, how to solve this?
I need both neighbor cells mutable returned from neighbors, to make computations on them.
I could return immutable but then I cannot turn them into &mut Cells because that does not exist (undefined behavior). Whats the common idiom here?
Related
I have the following code (just an example) which can't satisfy the borrow checker.
One method modifies one field of the struct and calls another method to modify the other. The problem is when calling the second method it needs a parameter that depends on the struct. The call to second method doesn't work with argument &self.a and neither &mut self.a because that would be a second mutable borrow.
In the end I fixed it by having all the code in just one method, but that's ugly as hell (in my real problem).
How can this be solved? (I know the parameter &self.a is not required, but that's not the point I want to illustrate...)
struct ABC {
a: Vec<i32>, // no Copy trait
b: i32,
}
impl ABC {
fn new() -> ABC { ABC {a: vec![0,1], b: 10} }
fn first(&mut self) {
self.a.push(2); // updates one field
self.second(&self.a); // uses a method to update the other field
}
fn second(&mut self, x: &Vec<i32>) {
self.b += x[1];
}
}
fn main() {
let mut s = ABC::new();
s.first();
}
Playground here.
You already borrowed from self.a; so as long as that borrow is there, you cannot move out to a second method. You can use to_vec() to copy the data to the second method.
struct ABC {
a: Vec<i32>, // no Copy trait
b: i32,
}
impl ABC {
fn new() -> ABC { ABC {a: vec![0,1], b: 10} }
fn first(&mut self) {
self.a.push(2); // updates one field
self.second(self.a.to_vec());
}
fn second(&mut self, x: Vec<i32>) {
self.b += x[1];
}
}
fn main() {
let mut s = ABC::new();
s.first();
}
playground
But as indicated, it will copy the data.
The simplest would be to update self.b in first method. In that way we don't borrow twice from self.a
fn first(&mut self) {
self.a.push(2); // updates one field
self.b += self.a[1];
}
If second does not borrow from self, it will work as follow:
struct ABC {
a: Vec<i32>, // no Copy trait
b: i32,
}
impl ABC {
fn new() -> ABC {
ABC {
a: vec![0, 1],
b: 10,
}
}
fn first(&mut self) {
self.a.push(2); // updates one field
Self::second(&mut self.b, &self.a);
}
fn second(y: &mut i32, x: &Vec<i32>) {
*y += x[1];
}
}
fn main() {
let mut s = ABC::new();
s.first();
}
But it is not much different from updating self.b directly in first method.
EDIT: This question isn't relevant on versions of Rust >= 1.47 because "const generics" has started being implemented.
I'm trying to implement a sudoku solver in Rust for learning purposes. I'm trying to create a board with a fixed size (81) array of Cells (which is Copy) but I can't seem to get it to work. I can create a line of 9 Cells so I guess I'm running into the problem where there are only generics for TryFrom for up 32 for this kind of conversion.
Cell looks like this for now:
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
This works:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = std::iter::repeat(0)
.zip(0..9u8)
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 9]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
But this doesn't:
use std::convert::TryInto;
fn main() {
let cells: Vec<Cell> = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
let c: Box<[Cell; 81]> = cells.into_boxed_slice().try_into().unwrap();
println!("{:#?}", c);
}
I tried to use the code from std as a guide like this:
impl TryFrom<Box<[Cell]>> for Box<[Cell; 81]> {
type Error = Box<[Cell]>;
fn try_from(boxed_slice: Box<[Cell]>) -> Result<Self, Self::Error> {
if boxed_slice.len() == 81 {
Ok(unsafe { Box::from_raw(Box::into_raw(boxed_slice) as *mut [Cell; 91]) })
} else {
Err(boxed_slice)
}
}
}
but that runs into an error about conflicting implementations of trait which I guess makes sense.
I know I could just use a Vec or do something like [[Cell; 9]; 9] but I'd really like to understand what's going on. While trying to figure this out I've seen a number of similar questions where people were trying to use types that didn't implement Copy and that was the problem but that's not the case here and I can't figure out how to make this work.
The trait FromIterator is not implemented for slices, you can wrap it in a type and implement it yourself:
use core::iter::FromIterator;
#[derive(Debug, Default, Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
#[derive(Debug)]
struct Sudoku(Box<[Cell]>);
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = Vec::new();
for cell in iter {
v.push(cell)
}
Sudoku(v.into_boxed_slice())
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{:#?}", cells);
}
Playground
Edit:
You can also implement it for the specific size of the array. Which for the sudoku case should be ok, but in general you would like things to work in a more general way. Instead of the fixated size, you could write a macro that would write the implementation for any given size too.
Example:
use core::iter::FromIterator;
use std::fmt;
#[derive(Clone, Copy)]
struct Cell {
row: u8,
column: u8,
}
impl fmt::Display for Cell {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Cell: ({}, {})", self.row, self.column)
}
}
struct Sudoku([Cell; 81]);
impl fmt::Display for Sudoku {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for cell in self.0.iter() {
write!(f, "{}\n", cell)?;
}
Ok(())
}
}
impl FromIterator<Cell> for Sudoku {
fn from_iter<I: IntoIterator<Item=Cell>>(iter: I) -> Self {
let mut v = [Cell {row: 0, column: 0}; 81];
for (i, cell) in (0..81).zip(iter) {
v[i] = cell;
}
Sudoku(v)
}
}
fn main() {
let cells: Sudoku = (0..9u8).into_iter()
.flat_map(|x| {
std::iter::repeat(x)
.zip(0..9u8)
})
.map(|(row, column)| Cell { row, column} )
.collect();
println!("{}", cells);
}
Playground
One way of doing this is to create an array or vector ([0, 1, 2, ..., n] and then use the iter() method. However, it is not memory efficient at all.
I tried the following implementation:
pub struct StaticIxIter {
max: usize,
current: usize,
next: usize,
}
impl StaticIxIter {
pub fn new(max: usize) -> Self {
StaticIxIter {
max,
current: 0,
next: 0,
}
}
}
impl Iterator for StaticIxIter {
type Item = &usize;
fn next(&mut self) -> Option<Self::Item> {
if self.next >= self.max {
return None;
}
self.current = self.next;
self.next += 1;
Some(&self.current)
}
}
fn main() {
for element in StaticIxIter::new(10) {
println!("{}", element);
}
}
It won't compile:
error[E0106]: missing lifetime specifier
--> src/main.rs:18:17
|
18 | type Item = &usize;
| ^ expected lifetime parameter
For iterating over a list of numbers, you might want to use Rust's range iterator.
Take a look at this iterator example, where a range is used:
for element in 0..100 {
println!("{}", element);
}
Changing this to 0..max is also perfectly fine. Don't forget to wrap this range between brackets like (0..100).map(...) if you want to use iterator functions on it.
About borrowing; for borrowing iterator items, you need to have an owner for them. I recommend to keep your implementation as simple as possible. Why don't you borrow iterator items after you iterated over it, like this?
for element in 0..100 {
println!("{}", &element);
// ^- borrow here
}
I'm trying to return a mutable reference after doing some operation on it. This is best explained by a piece of code:
#[derive(PartialEq)]
pub enum Value {
Null,
Array(Vec<Value>),
}
impl Value {
pub fn new() -> Value {
Value::Array(Vec::new())
}
pub fn push<'a, T> (&'a mut self, value: T) -> Option<&'a mut Value>
where T:Into<Value> {
let temp = match *self {
Value::Array(ref mut vec) => {
vec.push(value.into());
true
},
_ => false,
};
if temp {
Some(self)
} else {
None
}
}
}
#[test]
fn push_test() {
let mut val = Value::new();
val.push(Value::Null);
assert!(val == Value::Array(vec![Value::Null]));
}
The play version is here. The workaround with boolean values is because I would be borrowing multiple times if I return Some(self) from within the match block. Is there an elegant way to implement the push function without using boolean values? If its possible to retain the function signature then its a bonus. Thank you!
The workaround with boolean values is because I would be borrowing multiple times if I return Some(self) from within the match block
Another option is to replace self temporally, so v can take the ownership of the vector (avoiding the borrow). After adding the new item to v, we reconstruct the self value:
// the lifetime 'a can be omitted
pub fn push<T>(&mut self, value: T) -> Option<&mut Value>
where T: Into<Value>
{
// replace put Value::Null on self and return the old value
match ::std::mem::replace(self, Value::Null) {
Value::Array(mut v) => {
v.push(value.into());
*self = Value::Array(v);
Some(self)
},
_ => None,
}
}
It seems that if you borrow a reference to a struct field, the whole struct is considered borrowed. I've managed to isolate and example of what I want to do. I just want to get a "read-only" reference to a field in B to obtain some data and then modify another field of B. Is there a idiomatic Rust way to do this?
struct A {
i: i32,
}
struct B {
j: i32,
a: Box<A>,
}
impl B {
fn get<'a>(&'a mut self) -> &'a A {
&*self.a
}
fn set(&mut self, j: i32) {
self.j = j
}
}
fn foo(a: &A) -> i32 {
a.i + 1
}
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let a_ref = b.get();
b.set(foo(a_ref));
}
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> src/main.rs:27:5
|
26 | let a_ref = b.get();
| - first mutable borrow occurs here
27 | b.set(foo(a_ref));
| ^ second mutable borrow occurs here
28 | }
| - first borrow ends here
It's a feature of the language. From the compiler point of view, there is no way for it to know that it's safe to call your set() function while a is borrowed via get().
Your get() function borrows b mutably, and returns a reference, thus b will remain borrowed until this reference goes out of scope.
You have several way of handling this:
Separate your two fields into two different structs
Move the code which needs to access both attribute inside a method of B
Make your attributes public, you will thus be able to directly get references to them
Compute the new value before setting it, like this:
fn main() {
let a = Box::new(A { i: 47 });
let mut b = B { a: a, j: 1 };
let newval = {
let a_ref = b.get();
foo(a_ref)
};
b.set(newval);
}
Expanding a bit on Levans' answer
Move the code which needs to access both attribute inside a method of B
That might look like this at a first pass:
impl B {
fn do_thing(&mut self) {
self.j = self.a.foo()
}
}
However, this hard-codes the call to foo. You could also accept a closure to allow this to be more flexible:
impl B {
fn update_j_with_a<F>(&mut self, f: F)
where
F: FnOnce(&mut A) -> i32,
{
self.j = f(&mut self.a)
}
}
// ...
b.update_j_with_a(|a| a.foo())
Separate your two fields into two different structs
This is also applicable when you have borrowed two disjoint subsets of attributes. For example:
struct A {
description: String,
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.build_description()
// cannot borrow `*self` as immutable because `self.description` is also borrowed as mutable
}
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
Can be changed into
struct A {
description: String,
info: Info,
}
struct Info {
name: String,
age: u8,
money: i32,
}
impl A {
fn update_description(&mut self) {
let description = &mut self.description;
*description = self.info.build_description()
}
}
impl Info {
fn build_description(&self) -> String {
format!(
"{} is {} years old and has {} money",
self.name,
self.age,
self.money
)
}
}
fn main() {}
You can combine these two steps (and I'd say that it's better practice) and move the method onto the inner struct.