I am going through a Rust book at the moment. In it, it states that if I want to be able to reuse the container used in a for loop, after the loop, I will need to prefix it with & (borrow it?). However, I have tried those four scenarios and they all give me the same result.
Segment 2 reuses the container from Segment 1.
Segment 3 and Segment 4 use & with the same outcome.
What am I missing?
fn main() {
let _needle = 32;
let haystack = [1, 1, 2, 5, 14, 42, 132, 429, 1430, 4862];
// Segment 1
for item in haystack {
let result = match item {
42 | 132 => "hit",
_ => "miss"
};
if result == "hit" {
println!("{}: {}", item, result);
}
}
// Segment 2
for item in haystack {
let result = match item {
42 | 132 => "hit",
_ => "miss"
};
if result == "hit" {
println!("{}: {}", item, result);
}
}
// Segment 3
for item in &haystack {
let result = match *item {
42 | 132 => "hit",
_ => "miss"
};
if result == "hit" {
println!("{}: {}", *item, result);
}
}
// Segment 4
for item in &haystack {
let result = match item {
42 | 132 => "hit",
_ => "miss"
};
if result == "hit" {
println!("{}: {}", item, result);
}
}
println!("{}", haystack[0]);
}
Results:
42: hit
132: hit
42: hit
132: hit
42: hit
132: hit
42: hit
132: hit
1
The "trick" is that haystack is a [i32; N], and, according to the docs,
Arrays of any size implement the following traits if the element type allows it:
Copy
Clone
Debug
IntoIterator (implemented for [T; N], &[T; N] and &mut [T; N])
PartialEq, PartialOrd, Eq, Ord
Hash
AsRef, AsMut
Borrow, BorrowMut
So it's actually impossible to move out of haystack because it's Copy. If you replace it with a Vec<i32> you'll get the behavior you expect.
Related
I'm trying to solve the RPN calculator exercise at exercism but stumbled upon this temporary value dropped while borrowed error that I can't seem to work out.
Here's my code:
#[derive(Debug)]
pub enum CalculatorInput {
Add,
Subtract,
Multiply,
Divide,
Value(i32),
}
pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
let mut stack = Vec::new();
for input in inputs {
match input {
CalculatorInput::Value(value) => {
stack.push(value);
},
operator => {
if stack.len() < 2 {
return None;
}
let second = stack.pop().unwrap();
let first = stack.pop().unwrap();
let result = match operator {
CalculatorInput::Add => first + second,
CalculatorInput::Subtract => first - second,
CalculatorInput::Multiply => first * second,
CalculatorInput::Divide => first / second,
CalculatorInput::Value(_) => return None,
};
stack.push(&result.clone());
}
}
}
if stack.len() != 1 {
None
} else {
Some(*stack.pop().unwrap())
}
}
And the error I get:
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:32:29
|
32 | stack.push(&result.clone());
| ^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
...
36 | if stack.len() != 1 {
| ----- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
If I understand correctly, the variable result is no loger live outside of the for loop (outside of the operator match branch indeed), that's why I cloned it, but it still gives me the same error.
How can I make a copy of the result which is owned by the stack Vec (if that's what I should do)?
Just for reference, and in case anybody fins this useful, this is the final solution taking into account all the help received:
use crate::CalculatorInput::{Add,Subtract,Multiply,Divide,Value};
#[derive(Debug)]
pub enum CalculatorInput {
Add,
Subtract,
Multiply,
Divide,
Value(i32),
}
pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
let mut stack: Vec<i32> = Vec::new();
for input in inputs {
match input {
Value(value) => {
stack.push(*value);
},
operator => {
if stack.len() < 2 {
return None;
}
let second: i32 = stack.pop().unwrap();
let first: i32 = stack.pop().unwrap();
let result: i32 = match operator {
Add => first + second,
Subtract => first - second,
Multiply => first * second,
Divide => first / second,
Value(_) => return None,
};
stack.push(result);
}
}
}
if stack.len() != 1 {
None
} else {
stack.pop()
}
}
No need to clone, because i32 implements the Copy trait.
The problem was that my vec was receiving an &i32 instead of i32, and thus rust infered it to be a Vec<&i32>.
The error is because Rust did not infer the type you expected.
In your code, the type of value is inferred to be &i32 because input is a reference of a element in inputs, and you push a value later, therefore the type of stack is inferred to be Vec<&i32>.
A best fix is to explicitly specify the type of stack:
let mut stack: Vec<i32> = Vec::new();
And because i32 has implemented Copy trait, you should never need to clone a i32 value, if it is a reference, just dereference it.
Fixed code:
#[derive(Debug)]
pub enum CalculatorInput {
Add,
Subtract,
Multiply,
Divide,
Value(i32),
}
pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
let mut stack: Vec<i32> = Vec::new();
for input in inputs {
match input {
CalculatorInput::Value(value) => {
stack.push(*value);
}
operator => {
if stack.len() < 2 {
return None;
}
let second = stack.pop().unwrap();
let first = stack.pop().unwrap();
let result = match operator {
CalculatorInput::Add => first + second,
CalculatorInput::Subtract => first - second,
CalculatorInput::Multiply => first * second,
CalculatorInput::Divide => first / second,
CalculatorInput::Value(_) => return None,
};
stack.push(result);
}
}
}
if stack.len() != 1 {
None
} else {
Some(stack.pop().unwrap())
}
}
You have the same behavior with this simple exemple
fn main() {
let mut stack = Vec::new();
let a = String::from("test");
stack.push(&a.clone());
//-------- ^
println!("{:?}", stack);
}
and the good way is to not borrow when clone.
fn main() {
let mut stack = Vec::new();
let a = String::from("test");
stack.push(a.clone());
//-------- ^
println!("{:?}", stack);
}
The variable should be used like this stack.push(result.clone()); and change code like this
pub fn evaluate(inputs: &[CalculatorInput]) -> Option<i32> {
let mut stack: Vec<i32> = Vec::new();
//---------------- ^
for input in inputs {
match input {
CalculatorInput::Value(value) => {
stack.push(value.clone());
//----------------- ^
},
operator => {
if stack.len() < 2 {
return None;
}
let second = stack.pop().unwrap();
let first = stack.pop().unwrap();
let result = match operator {
CalculatorInput::Add => first + second,
CalculatorInput::Subtract => first - second,
CalculatorInput::Multiply => first * second,
CalculatorInput::Divide => first / second,
CalculatorInput::Value(_) => return None,
};
stack.push(result.clone());
//-^
}
}
}
if stack.len() != 1 {
None
} else {
Some(stack.pop().unwrap())
//------- ^
}
}
For most operators that might overflow, Rust provides a checked version. For example, to test if an addition overflows one could use checked_add:
match 255u8.checked_add(1) {
Some(_) => println!("no overflow"),
None => println!("overflow!"),
}
This prints "overflow!". There is also a checked_shl, but according to the documentation it only checks if the shift is larger than or equal to the number of bits in self. That means that while this:
match 255u8.checked_shl(8) {
Some(val) => println!("{}", val),
None => println!("overflow!"),
}
is caught and prints "overflow!", This:
match 255u8.checked_shl(7) {
Some(val) => println!("{}", val),
None => println!("overflow!"),
}
simply prints 128, clearly not catching the overflow.
What is the correct way to check for any kind of overflow when shifting left?
I'm not aware of any idiomatic way of doing this, but something like implementing your own trait would work: Playground
The algorithm is basically to check if there are not fewer leading zeros in the number than the shift size
#![feature(bool_to_option)]
trait LossCheckedShift {
fn loss_checked_shl(self, rhs: u32) -> Option<Self>
where Self: std::marker::Sized;
}
impl LossCheckedShift for u8 {
fn loss_checked_shl(self, rhs: u32) -> Option<Self> {
(rhs <= self.leading_zeros()).then_some(self << rhs)
// in stable Rust
// if rhs <= self.leading_zeros() { Some(self << rhs) }
// else { None }
}
}
fn main() {
match 255u8.loss_checked_shl(7) {
Some(val) => println!("{}", val),
None => println!("overflow!"), // <--
}
match 127u8.loss_checked_shl(1) {
Some(val) => println!("{}", val), // <--
None => println!("overflow!"),
}
match 127u8.loss_checked_shl(2) {
Some(val) => println!("{}", val),
None => println!("overflow!"), // <--
}
}
You could do a complementary right-shift (right-shift by 8 - requested_number_of_bits) and check if 0 remains. If so, it means that no bits would be lost by left-shifting:
fn safe_shl(n: u8, shift_for: u8) -> Option<u8> {
if n >> (8 - shift_for) != 0 {
return None; // would lose some data
}
Some(n << shift_for)
}
One can also write a generic version that accepts any numeric type, including bigints (and which applied to u8 generates exactly the same code as above):
use std::mem::size_of;
use std::ops::{Shl, Shr};
fn safe_shl<T>(n: T, shift_for: u32) -> Option<T>
where
T: Default + Eq,
for<'a> &'a T: Shl<u32, Output = T> + Shr<u32, Output = T>,
{
let bits_in_t = size_of::<T>() as u32 * 8;
let zero = T::default();
if &n >> (bits_in_t - shift_for) != zero {
return None; // would lose some data
}
Some(&n << shift_for)
}
Playground
I was reading Rust docs and I saw this code:
fn first_word(s: &String) -> &str {
let bytes = s.as_bytes();
println!("{:?}", bytes.iter().enumerate());
for (i, &item) in bytes.iter().enumerate() {
println!("{}", i);
if item == b' ' {
print!("{}", &s[0..i]);
break;
}
}
&s[..]
}
fn main() {
let amir = String::from("amir ali ahmadi");
first_word(&amir);
println!("{:?}", b" ")
}
Why is i the index?
And why is &item the value?
When you call enumerate() on an iterator, you get an instance of an Enumerate, whose struct is defined like this:
pub struct Enumerate<I> {
iter: I,
count: usize,
}
In other words, Enumerate simply wraps the original iterator and also a count field which keeps track of the next index which will be fetched from the iterator. (There is a link to the source code within the Enumerate documentation.)
Each time the for loop calls next() on the Enumerate, it executes this method:
fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
let a = self.iter.next()?;
let i = self.count;
// Possible undefined overflow.
AddAssign::add_assign(&mut self.count, 1);
Some((i, a))
}
This returns an Option::Some which holds a tuple (i, a). The value of i is equal to the count field, so it is equal to the current iterator index. And the value of a is equal to the value returned by the call to iter.next() on the original iterator. The add_assign function has the effect of incrementing the count field value by 1.
Note that the ? after the call to iter.next() means that if the iterator contains no more items then Option::None will be returned instead, and the method will have finished.
As pointed out in the comments to your question, when you print the debug output of an Enumerate instance, you will see the nested iterator and the count field:
{
iter: Iter([97, 109, 105, 114, 32, 97, 108, 105, 32, 97, 104, 109, 97, 100, 105]),
count: 0
}
I am trying to implement a merge sort using processes but I have a problem using the waitpid function:
extern crate nix;
extern crate rand;
use nix::sys::wait::WaitStatus;
use rand::Rng;
use std::io;
use std::process::exit;
use std::thread::sleep;
use std::time::{Duration, Instant};
use nix::sys::wait::waitpid;
use nix::unistd::Pid;
use nix::unistd::{fork, getpid, getppid, ForkResult};
static mut process_count: i32 = 0;
static mut thread_count: i32 = 0;
fn generate_array(len: usize) -> Vec<f64> {
let mut my_vector: Vec<f64> = Vec::new();
for _ in 0..len {
my_vector.push(rand::thread_rng().gen_range(0.0, 100.0)); // 0 - 99.99999
}
return my_vector;
}
fn get_array_size_from_user() -> usize {
let mut n = String::new();
io::stdin()
.read_line(&mut n)
.expect("failed to read input.");
let n: usize = n.trim().parse().expect("invalid input");
return n;
}
fn display_array(array: &mut Vec<f64>) {
println!("{:?}", array);
println!();
}
fn clear_screen() {
print!("{}[2J", 27 as char);
//print!("\x1B[2J"); // 2nd option
}
pub fn mergeSort(a: &mut Vec<f64>, low: usize, high: usize) {
let middle = (low + high) / 2;
let mut len = (high - low + 1);
if (len <= 1) {
return;
}
let lpid = fork();
match lpid {
Ok(ForkResult::Child) => {
println!("Left Process Running ");
mergeSort(a, low, middle);
exit(0);
}
Ok(ForkResult::Parent { child }) => {
let rpid = fork();
match rpid {
Ok(ForkResult::Child) => {
println!("Right Process Running ");
mergeSort(a, middle + 1, high);
exit(0);
}
Ok(ForkResult::Parent { child }) => {}
Err(err) => {
panic!("Right process not created: {}", err);
}
};
}
Err(err) => {
panic!("Left process not created {}", err);
}
};
//waitpid(lpid, None);
//waitpid(rpid, None);
// Merge the sorted subarrays
merge(a, low, middle, high);
}
fn merge(a: &mut Vec<f64>, low: usize, m: usize, high: usize) {
println!("x");
let mut left = a[low..m + 1].to_vec();
let mut right = a[m + 1..high + 1].to_vec();
println!("left: {:?}", left);
println!("right: {:?}", right);
left.reverse();
right.reverse();
for k in low..high + 1 {
if left.is_empty() {
a[k] = right.pop().unwrap();
continue;
}
if right.is_empty() {
a[k] = left.pop().unwrap();
continue;
}
if right.last() < left.last() {
a[k] = right.pop().unwrap();
} else {
a[k] = left.pop().unwrap();
}
}
println!("array: {:?}", a);
}
unsafe fn display_process_thread_counts() {
unsafe {
println!("process count:");
println!("{}", process_count);
println!("thread count:");
println!("{}", thread_count);
}
}
unsafe fn process_count_plus_plus() {
process_count += 1;
}
unsafe fn thread_count_plus_plus() {
thread_count += 1;
}
fn print_time(start: Instant, end: Instant) {
println!("TIME:");
println!("{:?}", end.checked_duration_since(start));
}
fn main() {
println!("ENTER SIZE OF ARRAY \n");
let array_size = get_array_size_from_user();
let mut generated_array = generate_array(array_size);
clear_screen();
println!("GENERATED ARRAY: \n");
display_array(&mut generated_array);
// SORTING
let start = Instant::now();
mergeSort(&mut generated_array, 0, array_size - 1);
let end = Instant::now();
// RESULT
//unsafe{
// process_count_plus_plus();
// thread_count_plus_plus();
//}
println!("SORTED ARRAY: \n");
display_array(&mut generated_array);
print_time(start, end);
unsafe {
display_process_thread_counts();
}
}
I get these results without using waitpid for the vector [3, 70, 97, 74]:
array before comparison: [3, 70, 97, 74]
comparison: [97], [74]
array after comparison: [3, 70, 74, 97]
array before comparison: [3, 70, 97, 74]
comparison: [3], [70]
array after comparison: [3, 70, 97, 74]
array before comparison: [3, 70, 97, 74]
comparison: [3, 70], [97, 74] (should be [74, 97])
array after comparison: [3, 70, 97, 74]
This has nothing to do with waitpid and everything to do with fork. When you fork a process, the OS creates a copy of your data and the child operates on this copy 1. When the child exits, its memory is discarded. The parent never sees the changes made by the child.
If you need the parent to see the changes made by the child, you should do one of the following:
Easiest and fastest is to use threads instead of processes. Threads share memory, so the parent and children all use the same memory. In Rust, the borrow checker ensures that parent and children behave correctly when accessing the same piece of memory.
Use mmap or something equivalent to share memory between the parent and children processes. Note however that it will be very difficult to ensure memory safety while the processes all try to access the same memory concurrently.
Use some kind of Inter-Process Communication (IPC) mechanism to send the result back from the children to the parent. This is easier than mmap since there is no risk of collision during memory accesses but in your case, given the amount of data that will need to be sent, this will be the slowest.
1 Actually, it uses Copy-On-Write, so data that is simply read is shared, but anything that either the parent or child writes will be copied and the other will not see the result of the write.
When using a match to modify a mutable variable, I haven't found a way to use match in a way that is guaranteed to be non-exhaustive and not requiring clone.
struct Stuff {
num: u32,
thing: bool,
}
enum Bar {
Nothing,
SomeStuff(Stuff),
AlsoNothing,
}
fn main() {
let mut things = vec![Bar::SomeStuff(Stuff {
num: 2,
thing: false,
})];
for x in things.iter_mut() {
*x = match *x {
Bar::Nothing => Bar::AlsoNothing,
Bar::AlsoNothing => Bar::SomeStuff(Stuff {
num: 3,
thing: true,
}),
Bar::SomeStuff(thing) => panic!("not sure"),
}
}
}
error[E0507]: cannot move out of borrowed content
--> src/main.rs:19:20
|
19 | *x = match *x {
| ^^ cannot move out of borrowed content
...
25 | Bar::SomeStuff(thing) => panic!("not sure"),
| ----- hint: to prevent move, use `ref thing` or `ref mut thing`
My intent is to write Bar::SomeStuff(thing) => Bar::SomeStuff(thing) and effectively leave it unchanged, but I cannot move through with a borrow or a reference.
Bar::SomeStuff(thing.clone()) could work, but copying a big struct could be very expensive.
Removing the *x = and changing to () could also work, but I am only returning a Bar enum so having the compiler check the return type is something I hope to keep.
If you want to pass a value unchanged, just capture the match with a variable and pass that back, e.g.
fn foo(a: u32) -> u32 {
match a {
0 => 1,
1 => 2,
e => e,
}
}
In your case, I would move the variable assignment into the match arms
for x in things.iter_mut() {
match x {
Bar::Nothing => *x = Bar::AlsoNothing,
Bar::AlsoNothing => *x = Bar::SomeStuff(Stuff { num: 3, thing: true }),
_ => {},
}
}