Taking ownership of vector twice - rust

I am trying to figure out the best way to use two functions on the same vector? I'm able to get both functions to do what I need them to do but as soon as I want to use them both on the same vector, I can't seem to make that compile "reasonably". I imagine I can just stick a bunch of muts and &s everywhere but that seems like a lot just to get two functions to run on the same vector as opposed to one. Am I missing some best practice here that can make this simpler?
Current code that fails compilation with v is a `&` reference error:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&vec))
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &Vec<i32>) -> i32 {
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}

You cannot do that. Rust requires you to think about ownership and constness very deeply. For example, your median function seems to sort vector internally: you should either allow it to modify the argument passed (median(v: &mut Vec<i32>) in the function definition and &mut v in the argument) or make a copy explicitly inside. However, if you allow mutating the vector, the original vector should be mutable itself (let mut vec). So, you can hack your way through like this:
fn main() {
let mut vec = vec![1,2,1,4,5]; // !
println!("Mean: {}, Median: {}", mean(&vec), median(&mut vec)) // !
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &mut Vec<i32>) -> i32 { // !
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}
However, making median modify the vector it analyzes seems very weird to me. I think it would be better to make an explicit copy and sorting it:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&vec))
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &Vec<i32>) -> i32 { // !
let v_sorted = v.sorted(); // creates a copy
let med_idx = v.len() / 2 as usize;
v[med_idx]
}
If you don't want the penalty, you can stick with the first solution and just create a copy on call site. This gives the most flexibility:
fn main() {
let vec = vec![1,2,1,4,5];
println!("Mean: {}, Median: {}", mean(&vec), median(&mut vec.clone())) // !
}
fn mean(v: &Vec<i32>) -> i32 {
v.iter().sum::<i32>() / v.len() as i32
}
fn median(v: &mut Vec<i32>) -> i32 { // !
v.sort();
let med_idx = v.len() / 2 as usize;
v[med_idx]
}

Related

Is there a trait that works for both VecDeque and Vec?

We can pass a Vec<f64> to this function, but we cannot pass a VecDeque, because that is two slices:
fn mean(v: &[f64]) -> f64 {
let sum = v.iter().sum();
sum / v.len() as f64
}
Is there a trait, something perhaps analogous to a C++ RandomAccessContainer, that allows us to generically write code that operates on both Vec and VecDeque?
You can just chain traits, like Index<usize, Output = f64> to get elements at an index, and IntoIterator<Item = &f64> to use IntoIterator. If you need len, then you can make your own trait and impl it.
There are 2 approaches:
Make your function accept a slice of slices: fn mean(&[&[f64]]) -> f64.
Can be called like mean(&[v.as_slice()])
Make it accept Iterator. I think this it is most acceptable way to allow use both VecDeque and Vec:
use std::collections::VecDeque;
use std::iter::Iterator;
use std::vec::Vec;
fn mean<T: Iterator<Item = f64>>(iter: T) -> f64 {
let (last_index, sum) = iter
.enumerate()
.fold((0, 0.0), |(_, sum), (i, v)| (i, sum + v));
sum / (last_index as f64 + 1.0)
}
fn main() {
let v: Vec<f64> = vec![0.0, 1.0, 2.0, 3.0, 4.0];
println!("{:?}", mean(v.iter().copied()));
let v: VecDeque<f64> = v.into();
println!("{:?}", mean(v.iter().copied()));
}
I believe you can use Iterator as a parameter.
There is a good article about iterator usage.
There is an alternate approach that is worth considering in these cases,
rather than looking for a trait that both types A and B implement that you
can pass into to your function, you create a new trait that both support, and use your new trait instead of the function. It usually means a little bit of duplication and boilerplate, but it is nicely extensible later.
trait HasMeanF64 {
fn mean(&self) -> f64;
}
impl HasMeanF64 for &[f64] {
fn mean(&self) -> f64 {
self.iter().sum::<f64>() / self.len() as f64
}
}
impl HasMeanF64 for Vec<f64> {
fn mean(&self) -> f64 {
self.iter().sum::<f64>() / self.len() as f64
}
}
impl HasMeanF64 for VecDeque<f64> {
fn mean(&self) -> f64 {
self.iter().sum::<f64>() / self.len() as f64
}
}
Now instead of writing mean(v) you can write v.mean().
And if you still want your mean(v) form you can write
fn mean<T: HasMeanF64>(v: &T) -> f64 {
v.mean()
}

Mutable borrow into two parts with cleanup

I have some object that I want to split into two parts via a mutable borrow, then combine those back together into the original object when the split references go out of scope.
The simplified example below is for a Count struct that holds a single i32, which we want to split into two &mut i32s, who are both incorporated back into the original Count when the two mutable references go out of scope.
The approach I am taking below is to use an intermediate object CountSplit which holds a mutable reference to the original Count object and has the Drop trait implemented to do the re-combination logic.
This approach feels kludgy. In particular, this is awkward:
let mut ms = c.make_split();
let (x, y) = ms.split();
Doing this in one line like let (x, y) = c.make_split().split(); is not allowed because the intermediate object must have a longer lifetime. Ideally I would be able to do something like let (x, y) = c.magic_split(); and avoid exposing the intermediate object altogether.
Is there a way to do this which doesn't require doing two let's every time, or some other way to tackle this pattern that would be more idiomatic?
#[derive(Debug)]
struct Count {
val: i32,
}
trait MakeSplit<'a> {
type S: Split<'a>;
fn make_split(&'a mut self) -> Self::S;
}
impl<'a> MakeSplit<'a> for Count {
type S = CountSplit<'a>;
fn make_split(&mut self) -> CountSplit {
CountSplit {
top: self,
second: 0,
}
}
}
struct CountSplit<'a> {
top: &'a mut Count,
second: i32,
}
trait Split<'a> {
fn split(&'a mut self) -> (&'a mut i32, &'a mut i32);
}
impl<'a, 'b> Split<'a> for CountSplit<'b> {
fn split(&mut self) -> (&mut i32, &mut i32) {
(&mut self.top.val, &mut self.second)
}
}
impl<'a> Drop for CountSplit<'a> {
fn drop(&mut self) {
println!("custom drop occurs here");
self.top.val += self.second;
}
}
fn main() {
let mut c = Count { val: 2 };
println!("{:?}", c); // Count { val: 2 }
{
let mut ms = c.make_split();
let (x, y) = ms.split();
println!("split: {} {}", x, y); // split: 2 0
// each of these lines correctly gives a compile-time error
// c.make_split(); // can't borrow c as mutable
// println!("{:?}", c); // or immutable
// ms.split(); // also can't borrow ms
*x += 100;
*y += 5000;
println!("split: {} {}", x, y); // split: 102 5000
} // custom drop occurs here
println!("{:?}", c); // Count { val: 5102 }
}
playground:
I don't think a reference to a temporary value like yours can be made to work in today's Rust.
If it's any help, if you specifically want to call a function with two &mut i32 parameters like you mentioned in the comments, e.g.
fn foo(a: &mut i32, b: &mut i32) {
*a += 1;
*b += 2;
println!("split: {} {}", a, b);
}
you can already do that with the same number of lines as you'd have if your chaining worked.
With the chaining, you'd call
let (x, y) = c.make_split().split();
foo(x, y);
And if you just leave out the conversion to a tuple, it looks like this:
let mut ms = c.make_split();
foo(&mut ms.top.val, &mut ms.second);
You can make it a little prettier by e.g. storing the mutable reference to val directly in CountSplit as first, so that it becomes foo(&mut ms.first, &mut ms.second);. If you want it to feel even more like a tuple, I think you can use DerefMut to be able to write foo(&mut ms.0, &mut ms.1);.
Alternatively, you can of course formulate this as a function taking a function
impl Count {
fn as_split<F: FnMut(&mut i32, &mut i32)>(&mut self, mut f: F) {
let mut second = 0;
f(&mut self.val, &mut second);
self.val += second;
}
}
and then just call
c.as_split(foo);

borrowed value does not live long enough in this case ( Vec<&Fn(i32) -> i32> )

I am having this error, other times I had something similar and I have been able to solve, in different ways but now is not how to solve in this case:
borrowed value does not live long enough in
I moved the code that fails one more simple, but I can not find the error:
fn main(){
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
v.push(&ops_code1);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
..//
error: borrowed value does not live long enough
v.push(&ops_code1);
play.rust
What you are doing here is creating a Vec of closures. In Rust static functions are treated slightly differently from closures, so when we create the reference a closure is actually created. If we do that after creating the Vec the resulting closure gets a shorter lifetime than the Vec, which is an error. We can instead use a let to create the closure before the Vec, giving a long enough lifetime, outliving the Vec:
fn main() {
let extended = &ops_code1;
let mut v: Vec<&Fn(i32) -> i32> = Vec::new();
// Note that placing it here does not work:
// let extended = &ops_code1;
v.push(extended);
//v.push(&ops_code2);
//v.push(&ops_code3);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
Rust Playground
However, if you only use static functions - and not closures - the following also works fine, and lets you avoid the extra let:
fn main() {
let mut v: Vec<fn(i32) -> i32> = Vec::new();
v.push(ops_code1);
v.push(ops_code2);
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground
A third option is to use boxed closures, which let's you use both closures and static functions without the extra lets, but with its own trade-offs:
fn main() {
let mut v: Vec<Box<Fn(i32) -> i32>> = Vec::new();
v.push(Box::new(ops_code1));
v.push(Box::new(ops_code2));
for f in v {
f(1);
}
}
fn ops_code1(value: i32) -> i32 {
println!("ops_code1 {}", value);
value
}
fn ops_code2(value: i32) -> i32 {
println!("ops_code2 {}", value);
value
}
Rust Playground

How to slice a large Vec<i32> as &[u8]?

I don't know how to convert a Vec<i32> into a &[u8] slice.
fn main() {
let v: Vec<i32> = vec![1; 100_000_000];
let v_bytes: &[u8] = /* ... */;
}
I want to write a large Vec<i32> to a file so I can read it back at a future time.
You can use std::slice::from_raw_parts:
let v_bytes: &[u8] = unsafe {
std::slice::from_raw_parts(
v.as_ptr() as *const u8,
v.len() * std::mem::size_of::<i32>(),
)
};
Following the comments on this answer, you should wrap this code in a function and have the return value borrow the input, so that you use the borrow checker as far as possible:
fn as_u8_slice(v: &[i32]) -> &[u8] {
unsafe {
std::slice::from_raw_parts(
v.as_ptr() as *const u8,
v.len() * std::mem::size_of::<i32>(),
)
}
}
Since Rust 1.30, the best solution is to use slice::align_to:
fn main() {
let v: Vec<i32> = vec![1; 8];
let (head, body, tail) = unsafe { v.align_to::<u8>() };
assert!(head.is_empty());
assert!(tail.is_empty());
println!("{:#x?}", body);
}
This properly handles the cases where the alignment of the first type and the second type do not match. In this example, I ensure that the alignment of the i32 is greater than that of the u8 via the assert! statements.
I took #swizards answer and ran with it a bit to get the other side of the coin - reading the vector back in:
use std::fs::File;
use std::io::{Read, Write};
use std::{mem, slice};
fn as_u8_slice(v: &[i32]) -> &[u8] {
let element_size = mem::size_of::<i32>();
unsafe { slice::from_raw_parts(v.as_ptr() as *const u8, v.len() * element_size) }
}
fn from_u8(v: Vec<u8>) -> Vec<i32> {
let data = v.as_ptr();
let len = v.len();
let capacity = v.capacity();
let element_size = mem::size_of::<i32>();
// Make sure we have a proper amount of capacity (may be overkill)
assert_eq!(capacity % element_size, 0);
// Make sure we are going to read a full chunk of stuff
assert_eq!(len % element_size, 0);
unsafe {
// Don't allow the current vector to be dropped
// (which would invalidate the memory)
mem::forget(v);
Vec::from_raw_parts(
data as *mut i32,
len / element_size,
capacity / element_size,
)
}
}
fn do_write(filename: &str, v: &[i32]) {
let mut f = File::create(filename).unwrap();
f.write_all(as_u8_slice(v)).unwrap();
}
fn do_read(filename: &str) -> Vec<i32> {
let mut f = File::open(filename).unwrap();
let mut bytes = Vec::new();
f.read_to_end(&mut bytes).unwrap();
from_u8(bytes)
}
fn main() {
let v = vec![42; 10];
do_write("vector.dump", &v);
let v2 = do_read("vector.dump");
assert_eq!(v, v2);
println!("{:?}", v2)
}

How can I iterate over a vector of functions and call each of them?

I'm trying to use a for loop to iterate over a vector of functions and execute each function at each step.
fn f1(i: i32) -> i32 {
i * 2
}
fn f2(i: i32) -> i32 {
i * 4
}
fn main() {
let mut arr: Vec<|i32| -> i32> = Vec::new();
arr.push(f1);
arr.push(f2);
for f in arr.iter() {
println!("{}", f(1));
}
}
But the attempted execution of f(1) gives this error:
error: expected function, found '&|i32| -> i32'
I guess in putting the functions in the vector their type is mutated and no longer works like a normal function. Is there a way to transform it back, or am I missing something?
As of Rust 1.x, unboxed closures are the only kind of closures in the language, and they don't need a feature flag. Moreover, static functions can easily be converted to unboxed closures. Therefore, the correct way to call functions from a vector of functions is:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<&dyn Fn(i32) -> i32> = vec![&f1, &f2];
for f in &arr {
println!("{}", (f)(1));
}
}
I've used Fn() closures which can access their environment through a shared reference, so it is sufficient to iterate the vector by reference. If I had used a FnMut() closure, I would have had to use iteration by mutable reference:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let p1 = &mut f1;
let p2 = &mut f2;
let mut arr: Vec<&mut dyn FnMut(i32) -> i32> = vec![p1, p2];
for f in &mut arr {
println!("{}", (f)(1));
}
}
A similar idea holds for FnOnce() and iteration by value, although here we need to use Box to own the closure:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<Box<dyn FnOnce(i32) -> i32>> = vec![Box::new(f1), Box::new(f1)];
for f in arr {
println!("{}", (f)(1));
}
}
Alternatively, if you know that you only work with static functions, it is possible to store pointers to them directly, without using closure traits:
fn f1(i: i32) -> i32 { i * 2 }
fn f2(i: i32) -> i32 { i * 4 }
fn main() {
let arr: Vec<fn(i32) -> i32> = vec![f1, f2];
for f in &arr {
println!("{}", (f)(1));
}
}
While f1 and f2 actually have different incompatible types, they are automatically coerced to the general function pointer type fn(i32) -> i32 when used in appropriate context, like in the example above.
Because static functions don't have any environment, you can freely clone references to them and call them through any kind of reference. This is probably the way to go if you only need static functions.
This answer was updated for Rust 1.x; older versions of the answer remain in the edit history.

Resources