I am trying to teach myself Rust with Project Euler Problems, specifically https://projecteuler.net/problem=76.
I came up with a solution to the problem of:
fn main() {
println!("{}", solution(100, 99));
}
fn solution(sum_to: i32, max_size: i32) -> i32 {
if sum_to == 0 || max_size == 1 {
1
} else if sum_to < 0 {
0
} else {
(1..=max_size)
.map(|i| solution(sum_to - i, min(i, sum_to - i)))
.sum()
}
}
I know this works, but it takes forever to run because it winds up computing result for the same input multiple times.
I tried building a caching solution to this, but I run into problems with the borrow checker.
Code:
use std::cmp::min;
use std::collections::HashMap;
fn main() {
println!("{}", solution_head(100))
}
fn solution_head(sum_to: i32) -> i32 {
let mut cache = HashMap::new();
(1..sum_to)
.map(|i| solution(&mut cache, sum_to - i, min(i, sum_to - i)))
.sum()
}
fn solution(
cache: &mut HashMap<i32, HashMap<i32, i32>>,
sum_to: i32,
max_size: i32,
) -> i32 {
if sum_to == 0 {
1
} else if sum_to < 0 {
0
} else {
let cache_entry = cache.entry(sum_to);
let map = cache_entry.or_insert(HashMap::new());
let map_entry = map.entry(max_size);
*map_entry.or_insert_with(|| {
(1..=max_size)
.map(|i| solution(cache, sum_to - i, min(i, sum_to - i)))
.sum()
})
}
}
Error:
error[E0500]: closure requires unique access to `*cache` but it is already borrowed
--> src/bin/problem_76.rs:27:35
|
24 | let cache_entry = cache.entry(sum_to);
| ------------------- borrow occurs here
...
27 | *map_entry.or_insert_with(|| {
| -------------- ^^ closure construction occurs here
| |
| first borrow later used by call
28 | (1..=max_size)
29 | .map(|i| solution(cache, sum_to - i, min(i, sum_to - i)))
| ----- second borrow occurs due to use of `*cache` in closure
I am not at all certain of how to accomplish this, as the ultimate problem that the borrow checker has with this code is that I am both:
using a reference to the cache in the function to check if I have already computed the result
sending a reference to the cache to recursive call of the function so that I can check if I have already computed the downstream result
What is the proper, idiomatic way of accomplishing this in Rust?
The problem is that cache_entry points to a value inside cache which means you cannot modify cache while the entry is in scope. I would restructure the code to use .get() and .insert(). I would also simplify cache to be HashMap<(i32, i32), i32>.
The following code works fast for me:
use std::collections::HashMap;
fn main() {
let mut cache = HashMap::new();
println!("{}", solution(&mut cache, 100, 99));
}
fn solution(cache: &mut HashMap<(i32, i32), i32>, sum_to: i32, max_size: i32) -> i32 {
if sum_to == 0 || max_size == 1 {
1
} else if sum_to < 0 {
0
} else if let Some(x) = cache.get(&(sum_to, max_size)) {
*x
} else {
let x = (1..=max_size)
.map(|i| solution(cache, sum_to - i, std::cmp::min(i, sum_to - i)))
.sum();
cache.insert((sum_to, max_size), x);
x
}
}
Playground
Related
CONTEXT
General overview
(Here is the github page with the minimal example of my problem, and the page of my whole project)
I'm very new to rust and I'm trying to simulate the behavior of a fluid in Rust. This is easy: computing large arrays with some functions for each timestep.
I'd like to parallelize the computations done each timestep using rayon. But the compiler doesn't want me to access a mutable struct containing an Array that I want to modify, even if I'm sure that each modification will be on different places in the array: which assure me that it's safe. (I think?).
So my question is: should I use unsafe rust in here? If so, how?
And: is it possible to make Rust understand that it's safe, or to do it properly without unsafe rust?
I saw this post which kind of resembled my problem, but couldn't find a way to use the solution for my problem.
I also tried to put unsafe {...} keywords everywhere, but the compilator still complains...
You may only need to read "Structs" subsection to understand the problem, but I will also put a "Function" subsection, in case it can be important. If you think it might not be necessary, you can skip to "Main function" subsection.
Structs
Here are my structs:
I'd like to keep them that way, as they would give me (I think) more flexibility with setters/getters, but I'm open to change the way it's implemented right now.
#[derive(Debug, PartialEq)]
struct vec2D {pub x: f64, pub y: f64}
#[derive(Debug, PartialEq)]
struct ScalarField2D {
s: Array2<f64>,
}
#[derive(Debug, PartialEq)]
struct VectorField2D {
x: ScalarField2D,
y: ScalarField2D
}
impl ScalarField2D {
// also a constructor new() but not shown for simplicity
fn get_pos(&self, x: usize, y: usize) -> f64
{return self.s[[y,x]];}
fn set_pos(&mut self, x: usize, y: usize, f: f64)
{self.s[[y,x]] = f;}
}
impl VectorField2D {
// also a constructor new() but not shown for simplicity
fn get_pos(&self, x: usize, y: usize) -> vec2D
{let vec_at_pos = vec2D {
x: self.x.get_pos(x, y),
y: self.y.get_pos(x, y)};
return vec_at_pos;}
fn set_pos(&mut self, x: usize, y: usize, vec: &vec2D)
{self.x.set_pos(x, y, vec.x);
self.y.set_pos(x, y, vec.y);}
}
Function
Here is my function: which takes a ScalarField2D struct, and computes a vector called the "gradient" at a particular position of the ScalarField2D array, and then returning this vector as a "vec2D" struct.
// computes the gradient of a scalar field at a given position
fn grad_scalar(a: &ScalarField2D,
x: i32, y: i32,
x_max: i32, y_max: i32) -> vec2D
{
let ip = ((x+1) % x_max) as usize;
// i-1 with Periodic Boundaries
let im = ((x - 1 + x_max) % x_max) as usize;
// j+1 with Periodic Boundaries
let jp = ((y+1) % y_max) as usize;
// j-1 with Periodic Boundaries
let jm = ((y - 1 + y_max) % y_max) as usize;
let (i, j) = (x as usize, y as usize);
let grad = vec2D {
x: (a.get_pos(ip, j) - a.get_pos(im, j))/(2.),
y: (a.get_pos(i, jp) - a.get_pos(i, jm))/(2.)};
return grad;
}
Main function
Here is my problem:
I try to iterate over all the possible x and y using (0..x_max).into_par_iter() (or y_max for y), compute the gradient associated with each position, and then set the value to the ScalarField2D struct using the set_pos method... Here is the main function, and the import commands, and I will show you the error message I get in the next subsection
use ndarray::prelude::*;
use rayon::prelude::*;
fn main() {
let (x_max, y_max) = (2usize, 50usize);
let (x_maxi32, y_maxi32) = (x_max as i32, y_max as i32);
let mut GD_grad_rho = VectorField2D::new(x_max, y_max);
let mut GD_rho = ScalarField2D::new(x_max, y_max);
let x_iterator = (0..x_max).into_par_iter();
x_iterator.map(|xi| {
let y_iterator = (0..y_max).into_par_iter();
y_iterator.map(|yi| {
// unsafe here?
GD_grad_rho
.set_pos(xi, yi,
&grad_scalar(&GD_rho,
xi as i32, yi as i32,
x_maxi32, y_maxi32));
});});
}
Error message
Here is the compilation error I get
error[E0596]: cannot borrow `GD_grad_rho` as mutable, as it is a captured variable in a `Fn` closure
--> src/main.rs:104:13
|
104 | / GD_grad_rho
105 | | .set_pos(xi, yi,
106 | | &grad_scalar(&GD_rho,
107 | | xi as i32, yi as i32,
108 | | x_maxi32, y_maxi32));
| |__________________________________________________________^ cannot borrow as mutable
error[E0596]: cannot borrow `GD_grad_rho` as mutable, as it is a captured variable in a `Fn` closure
--> src/main.rs:101:24
|
101 | y_iterator.map(|yi| {
| ^^^^ cannot borrow as mutable
...
104 | GD_grad_rho
| ----------- mutable borrow occurs due to use of `GD_grad_rho` in closure
For more information about this error, try `rustc --explain E0596`.
error: could not compile `minimal_example_para` due to 2 previous errors
If you want the complete thing, I created a github repo with everything in it.
Tests after susitsm answer
So I did something like this:
use ndarray::prelude::*;
use rayon::prelude::*;
fn grad_scalar(a: &Array2<f64>,
i: usize, j: usize) -> (f64, f64)
{
let array_shape = a.shape();
let imax = array_shape[0];
let jmax = array_shape[1];
// i-1 with Periodic Boundaries
let ip = ((i + 1) % imax);
// i-1 with Periodic Boundaries
let im = ((i + imax) - 1) % imax;
// j+1 with Periodic Boundaries
let jp = ((j + 1) % jmax);
// j-1 with Periodic Boundaries
let jm = ((j + jmax) - 1) % jmax;
let grad_i = (a[[ip, j]] - a[[im, j]])/2.;
let grad_j = (a[[i, jp]] - a[[i, jm]])/2.;
return (grad_i, grad_j);
}
fn main() {
let a = Array::<f64, Ix2>::ones((dim, dim));
let index_list: Vec<(_, _)> = (0..a.len())
.into_par_iter()
.map(|i| (i / a.dim().0, i % a.dim().1))
.collect();
let (r1, r2): (Vec<_>, Vec<_>) = (0..a.len())
.into_par_iter()
.map(|i| (index_list[i].0, index_list[i].1))
.map(|(i, j)| grad_scalar(&a, i, j))
.collect();
let grad_row = Array2::from_shape_vec(a.dim(), r1).unwrap();
let grad_col = Array2::from_shape_vec(a.dim(), r2).unwrap();
}
Which gives me the result I want, even though I wanted to access the values through my Structs. Which is not exactly what I want but we're getting closer
But I wonder about the efficiency for more arrays, I'll post a separate question for that
You can do something like this:
use ndarray::Array2;
use rayon::prelude::*;
fn main() {
let a: Vec<u64> = (0..20000).collect();
let a = Array2::from_shape_vec((100, 200), a).unwrap();
let stuff = |arr, i, j| (i + j, i * j);
let (x, y): (Vec<_>, Vec<_>) = (0..a.len())
.into_par_iter()
.map(|i| (i / a.dim().0, i % a.dim().1))
.map(|(i, j)| stuff(&a, i, j))
.collect();
let grad_x = Array2::from_shape_vec(a.dim(), x);
let grad_y = Array2::from_shape_vec(a.dim(), y);
let grad_vector_field = VectorField2D {
x: ScalarField2D { s: grad_x },
y: ScalarField2D { s: grad_y },
};
}
Or implement the FromParallelIterator<vec2D>
impl FromParallelIterator<vec2D> for VectorField2D {
fn from_par_iter<I>(par_iter: I) -> Self
where I: IntoParallelIterator<Item = T>
{
let (x, y): (Vec<_>, Vec<_>) = par_iter
.into_par_iter()
.map(|vec_2D| {
let vec2D { x, y } = vec_2D;
(x, y)
})
.collect();
Self {
x: ScalarField2D { s: Array2::from_shape_vec(a.dim(), x) },
y: ScalarField2D { s: Array2::from_shape_vec(a.dim(), y) },
}
}
}
This will enable using collect for your type when using parallel iterators
let vector_field: VectorField2D = (0..a.len())
.into_par_iter()
.map(|i| (index_list[i].0, index_list[i].1))
.map(|(i, j)| grad_scalar(&a, i, j))
.collect();
I'm trying to learn Rust after many years of C++. I have a situation where the compiler is complaining about a borrow, and it doesn't seem to matter whether it is mutable or immutable. I don't seem to be able to use self as a parameter inside a loop that start with: for item in self.func.drain(..).I've tried calling appropriate() as a function:
Self::appropriate(&self,&item,index)
and I have tried it as a method:
self.appropriate(&item,index)
but I get the same message in either case:
The function or method appropriate() is intended imply examine the relationship among its parameters and return a bool without modifying anything. How can I call either a function or method on self without violating borrowing rules?This program is a learning exercise from exercism.org and doesn't include a main() so it won't run but should almost compile except for the error in question. Here's the code I have:
use std::collections::HashMap;
pub type Value = i32;
pub type Result = std::result::Result<(), Error>;
pub struct Forth {
v: Vec<Value>,
f: HashMap<String,usize>,
s: Vec<Vec<String>>,
func: Vec<String>
}
#[derive(Debug, PartialEq)]
pub enum Error {
DivisionByZero,
StackUnderflow,
UnknownWord,
InvalidWord,
}
impl Forth {
pub fn new() -> Forth {
let mut temp: Vec<Vec<String>> = Vec::new();
temp.push(Vec::new());
Forth{v: Vec::<Value>::new(), f: HashMap::new(), s: temp, func: Vec::new()}
}
pub fn stack(&self) -> &[Value] {
&self.v
}
pub fn eval(&mut self, input: &str) -> Result {
self.v.clear();
self.s[0].clear();
let mut count = 0;
{
let temp: Vec<&str> = input.split(' ').collect();
let n = temp.len() as i32;
for x in 0..n as usize {
self.s[0].push(String::from(temp[x]));
}
}
let mut collecting = false;
let mut xlist: Vec<(usize,usize)> = Vec::new();
let mut sx: usize = 0;
let mut z: i32 = -1;
let mut x: usize;
let mut n: usize = self.s[0].len();
loop {
count += 1;
if count > 20 {break;}
z += 1;
x = z as usize;
if x >= n {break;}
z = x as i32;
let word = &self.s[sx][x];
if word == ";" {
if collecting {
collecting = false;
let index: usize = self.s.len();
self.s.push(Vec::<String>::new());
for item in self.func.drain(..) {
if self.s[index].len() > 0 &&
Self::appropriate(&self,&item,index)
{
let sx = *self.f.get(&self.s[index][0]).unwrap();
let n = self.s[sx].len();
for x in 1..n as usize {
let symbol = self.s[sx][x].clone();
self.s[index].push(symbol);
}
}
else {
self.s[index].push(item);
}
}
self.f.insert(self.s[index][0].clone(), index);
self.func.clear();
continue;
}
if 0 < xlist.len() {
(x, n) = xlist.pop().unwrap();
continue;
}
return Err(Error::InvalidWord);
}
if collecting {
self.func.push(String::from(word));
continue;
}
if Self::is_op(word) {
if self.v.len() < 2 {
return Err(Error::StackUnderflow);
}
let b = self.v.pop().unwrap();
let a = self.v.pop().unwrap();
let c = match word.as_str() {
"+" => a + b,
"-" => a - b,
"*" => a * b,
"/" => {if b == 0 {return Err(Error::DivisionByZero);} a / b},
_ => 0
};
self.v.push(c);
continue;
}
match word.parse::<Value>() {
Ok(value) => { self.v.push(value); continue;},
_ => {}
}
if word == ":" {
collecting = true;
self.func.clear();
continue;
}
if word == "drop" {
if self.v.len() < 1 {
return Err(Error::StackUnderflow);
}
self.v.pop();
continue;
}
if word == "dup" {
if self.v.len() < 1 {
return Err(Error::StackUnderflow);
}
let temp = self.v[self.v.len() - 1];
self.v.push(temp);
continue;
}
if !self.f.contains_key(word) {
return Err(Error::UnknownWord);
}
xlist.push((sx,n));
sx = *self.f.get(word).unwrap();
n = self.s[sx].len();
z = 0;
}
Ok(())
}
fn is_op(input: &str) -> bool {
match input {"+"|"-"|"*"|"/" => true, _ => false}
}
fn appropriate(&self, item:&str, index:usize) -> bool
{
false
}
fn prev_def_is_short(&self, index: usize) -> bool {
if index >= self.s.len() {
false
}
else {
if let Some(&sx) = self.f.get(&self.func[0]) {
self.s[sx].len() == 2
}
else {
false
}
}
}
}
The error message relates to the call to appropriate(). I haven't even written the body of that function yet; I'd like to get the parameters right first. The compiler's complaint is:
As a subroutine call
error[E0502]: cannot borrow `self` as immutable because it is also borrowed as mutable
--> src/lib.rs:85:47
|
81 | for item in self.func.drain(..) {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
...
85 | Self::appropriate(&self,&item,index)
| ^^^^^ immutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
as a method call
error[E0502]: cannot borrow `*self` as immutable because it is also borrowed as mutable
--> src/lib.rs:85:29
|
81 | for item in self.func.drain(..) {
| -------------------
| |
| mutable borrow occurs here
| mutable borrow later used here
...
85 | self.appropriate(&item,index)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ immutable borrow occurs here
For more information about this error, try `rustc --explain E0502`.
Is there any canonical way to deal with this situation?
The problem is that self.func.drain() will consume the elements contained in self.func, thus an exclusive (&mut) access is needed on self.func for the entire for loop.
If during the iteration you need to pass a reference to self globally, then its func member is potentially accessible while the loop holds an exclusive access to it: Rust forbids that.
Since you use drain() in order to consume all the elements inside self.func, I suggest you swap this vector with an empty one just before the loop, then iterate on this other vector that is not anymore part of self.
No copy of the content of the vector is involved here; swap() only deals with pointers.
Here is an over-simplified version of your code, adapted consequently.
struct Forth {
func: Vec<String>,
}
impl Forth {
fn eval(&mut self) {
/*
for item in self.func.drain(..) {
self.appropriate(&self);
}
*/
let mut func = Vec::new();
std::mem::swap(&mut self.func, &mut func);
for item in func.drain(..) {
let b = self.appropriate();
println!("{:?} {:?}", item, b);
}
}
fn appropriate(&self) -> bool {
false
}
}
fn main() {
let mut f = Forth {
func: vec!["aaa".into(), "bbb".into()],
};
f.eval();
}
I'm trying to return sum of 3 largest numbers in an array like this:
fn max_tri_sum(arr: &[i32]) -> i32 {
arr.sort();
arr[0]+arr[1]+arr[2]
}
but I keep getting this error:
error[E0596]: cannot borrow `*arr` as mutable, as it is behind a `&` reference
fn max_tri_sum(arr: &[i32]) -> i32 {
------ help: consider changing this to be a mutable reference: `&mut [i32]`
arr.sort();
^^^ `arr` is a `&` reference, so the data it refers to cannot be borrowed as mutable
I shouldn't change arr: &[i32] to arr: &mut [i32] because of some restrictions. So what can I do about it?
P.S: I tried to clone arr to a mutable variable but got other errors:
fn max_tri_sum(arr: &[i32]) -> i32 {
let a: &mut [i32] = *arr.clone();
a.sort();
a[0]+a[1]+a[2]
}
You could also use a BinaryHeap to store the three largest values so far and replace the smallest value while looping through the array:
use std::collections::BinaryHeap;
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut heap = BinaryHeap::new();
heap.push(-arr[0]);
heap.push(-arr[1]);
heap.push(-arr[2]);
for e in arr[3..].iter() {
if -e < *heap.peek().unwrap() {
heap.pop();
heap.push(-e);
}
}
-heap.drain().sum::<i32>()
}
Or if you prefer the sort option, you can convert the slice to a vector:
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut arr1 = arr.to_vec();
arr1.sort_by(|a, b| b.cmp(a));
arr1[0] + arr1[1] + arr1[2]
}
Playground
In Rust, you can't have a variable that has both reference and mutable reference in the same scope.
You have several choices :
You could simply do a loop on the slice to get the values you want. Something like this (there's probably a more elegant way with iterators)
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut maxes = [0, 0, 0];
for &el in arr {
if el > maxes[0] && el < maxes[1] {
maxes[0] = el;
} else if el > maxes[1] && el < maxes[2] {
if maxes[1] > maxes[0] {
maxes[0] = maxes[1];
}
maxes[1] = el;
} else if el > maxes[2] {
if maxes[2] > maxes[1] {
maxes[1] = maxes[2];
}
maxes[2] = el;
}
}
maxes[0] + maxes[1] + maxes[2]
}
You can create a new Vec from the slice, and then do all the operations on it (which requires allocation, but should be fine for small Vecs).
fn max_tri_sum(arr: &[i32]) -> i32 {
let mut arr = Vec::from(arr);
arr.sort();
arr[0] + arr[1] + arr[2]
}
I would also like to point that sort sorts from smallest to biggest, so the index 0, 1, 2, ... would be the smallest values in the array, which I don't think is what you want to do!
I have been having a problem trying to come up with a solution to read a binary tree from a formatted input and build said tree in Rust. The borrow checker has been driving crazy and thus decided to take to the community.
Basically, the input looks like this:
1 2 3 4 5 6 N N 7 8
and it represents a tree that looks like this:
1
/ \
2 3
/ \ / \
4 5 6 N
/ \ /
N 7 8
with N meaning NULL.
To read this, in CPP I would usually read this tree by level doing kind of a Breadth first building of the tree using a queue to do so.
I was attempting the same approach in Rust but that is where hell broke lose on me. I am a beginner in Rust and of course I am being scolded by the borrow checker.
I am using the following TreeNode structure:
#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
pub val: i32,
pub left: Option<Rc<RefCell<TreeNode>>>,
pub right: Option<Rc<RefCell<TreeNode>>>,
}
impl TreeNode {
#[inline]
pub fn new(val: i32) -> Self {
TreeNode {
val,
left: None,
right: None
}
}
}
And here is the piece of code that is doing the reading of the tree from STDIN:
fn read_b_tree<T: io::BufRead>(scan: &mut Scanner<T>, size: usize)
-> Result<Option<Rc<RefCell<TreeNode>>>, Box<dyn Error>> {
if size == 0 {
Ok(None)
} else {
let r = scan.token::<String>();
if r == "N" {
Ok(None)
} else {
let mut q = VecDeque::new();
let root = Rc::new(RefCell::new(TreeNode::new(r.parse::<i32>()?)));
q.push_back(&root);
let mut cnt: usize = 1;
while cnt < size && !q.is_empty() {
let node = match q.pop_front() {
Some(node) => Ok(node),
_ => Err("Queue should not be empty"),
}?;
let v = Rc::clone(node);
let left = scan.token::<String>();
let right = scan.token::<String>();
if left != "N" {
let left_n = Rc::new(RefCell::new(TreeNode::new(left.parse::<i32>()?)));
v.borrow_mut().left = Some(Rc::clone(&left_n));
q.push_back(&left_n);
}
cnt += 1;
if right != "N" {
let right_n = Rc::new(RefCell::new(TreeNode::new(right.parse::<i32>()?)));
v.borrow_mut().right = Some(Rc::clone(&right_n));
q.push_back(&right_n);
}
cnt += 1;
}
Ok(Some(root))
}
}
}
As you can imagine, I ran into lifetime issues with this approach, such as:
error[E0597]: `right_n` does not live long enough
--> src/main.rs:146:33
|
125 | while cnt < size && !q.is_empty() {
| - borrow later used here
...
146 | q.push_back(&right_n);
| ^^^^^^^^ borrowed value does not live long enough
147 | }
| - `right_n` dropped here while still borrowed
I would be highly thankful to anyone who could give some pointers as to how I work out of this situation.
Sincerely,
The following code is shorter and demonstrates your problem:
fn read_b_tree() -> Result<Option<Rc<RefCell<TreeNode>>>, Box<dyn Error>> {
let r = String::new();
let mut q = VecDeque::new();
let root = Rc::new(RefCell::new(TreeNode::new(r.parse::<i32>()?)));
q.push_back(&root);
while !q.is_empty() {
if r != "N" {
let left_n = Rc::new(RefCell::new(TreeNode::new(r.parse::<i32>()?)));
q.push_back(&left_n);
}
}
Ok(Some(root))
}
The inferred type of q is VecDeque<&Rc<RefCell<TreeNode>>>, yet there is no reason why you choose this instead of VecDeque<Rc<RefCell<TreeNode>>> (Rc instead of &Rc) - Rc is already a reference so there is no need to do it a second time.
I think you inserted the & because without & there was an error use of moved value .... This error is correct: You use root after moving it to q. But that is not a problem, because you wanted to move a Rc to q and you can easily get one new by just cloning it root.clone() or Rc::clone(&root).
The fixed example is:
fn read_b_tree() -> Result<Option<Rc<RefCell<TreeNode>>>, Box<dyn Error>> {
let r = String::new();
let mut q = VecDeque::new();
let root = Rc::new(RefCell::new(TreeNode::new(r.parse::<i32>()?)));
q.push_back(root.clone());
while !q.is_empty() {
if r != "N" {
let left_n = Rc::new(RefCell::new(TreeNode::new(r.parse::<i32>()?)));
q.push_back(left_n); //this works in the example, but you will have to clone here too
}
}
Ok(Some(root))
}
This question already has an answer here:
Value does not live long enough
(1 answer)
Closed 4 years ago.
I'm trying to turn a matrix A into matrix B where B_11 would be the biggest element of the first row and the smallest element of the second row in a tuple. So the matrix [1,2;3,4] would become [(2,1), (2,2); (4,1), (4,2)].
pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
let answer = Vec::new();
println!("matrix: {:?}", input);
let x: Vec<Vec<_>> = input
.iter()
.map(|row| {
row.iter()
.map(move |_| {
let y = get_column(&input, 0);
println!("y is {:?}", y);
let x = get_lowest(&y);
(get_highest(row), x)
}).collect()
}).collect();
println!("x is {:?}", x);
answer
}
fn get_highest(row: &Vec<u64>) -> &u64 {
row.iter().max().unwrap()
}
fn get_lowest(column: &Vec<u64>) -> &u64 {
column.iter().min().unwrap()
}
fn get_column(matrix: &[Vec<u64>], index: usize) -> Vec<u64> {
matrix.iter().map(|row| row[index]).collect()
}
I'm getting an error messages when I try to use y:
error[E0597]: `y` does not live long enough
--> src/lib.rs:11:41
|
11 | let x = get_lowest(&y);
| ^ borrowed value does not live long enough
12 | (get_highest(row), x)
13 | }).collect()
| - `y` dropped here while still borrowed
...
17 | }
| - borrowed value needs to live until here
I don't understand why the value y has to live until after it's used. Isn't it enough that it lives until after the get_lowest function?
How would I fix this?
You can use the clone() function to pass new copies of the vectors to the functions get_highest and get_lowest and make the functions return integers and not references with the funciton to_owned().
pub fn find_saddle_points(input: &[Vec<u64>]) -> Vec<(usize, usize)> {
let answer = Vec::new();
println!("matrix: {:?}", input);
let x: Vec<Vec<_>> = input
.iter()
.map(|row| {
row.iter()
.map(move |_| {
let y = get_column(&input, 0);
println!("y is {:?}", y);
let x = get_lowest(y.clone());
(get_highest(row), x)
}).collect()
}).collect();
println!("x is {:?}", x);
answer
}
fn get_highest(row: Vec<u64>) -> u64 {
row.iter().max().unwrap().to_owned()
}
fn get_lowest(column: Vec<u64>) -> u64 {
column.iter().min().unwrap().to_owned()
}
fn get_column(matrix: &[Vec<u64>], index: usize) -> Vec<u64> {
matrix.iter().map(|row| row[index]).collect()
}
And as #shepmaster posted, you should avoid using references of Vectors as function parameters.
Shepmaster explained it well
TL;DR — you created the Vec y and then got a reference to the vector
via get_highest and get_lowest. When you exit the closure, Vec is
destroyed and the references would point at nothing. The compiler is
preventing you from making a massive mistake that would lead to memory
unsafety in a language like C or C++.