How can I hold a boxed async function that captures variables? - asynchronous

I want to have a boxed async function from a closure that can capture variables:
use std::future::Future;
use std::pin::Pin;
fn constrain<Fun>(fun: Fun) -> Fun
where
Fun: for<'arg> Fn(&'arg usize, &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'arg>>,
{
fun
}
struct Test {}
impl Test {
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where
'arg: 'test,
{
*val0 + *val1
}
}
pub async fn fun<'arg>(val0: &'arg usize, val1: &'arg usize) -> usize {
val0 + val1
}
#[tokio::main(flavor = "current_thread")]
async fn main() {
let test = Test {};
let boxed = Box::new(constrain(move |v0, v1| {
let ret = Box::pin(async {
test.fun(v0, v1).await
//fun(v0, v1).await
});
ret
}));
let v0 = 10;
let v1 = 20;
let ret = boxed(&v0, &v1).await;
println!("{ret}");
}
When I call 'fun', it works, because it doesn't capture 'test'. When I call 'test.fun(...)', it fails:
error: lifetime may not live long enough
--> src/main.rs:46:9
|
38 | let boxed = Box::new(constrain(move |v0, v1|
| -------------
| | |
| | has type `&'2 usize`
| lifetime `'1` represents this closure's body
...
46 | ret
| ^^^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
|
= note: closure implements `Fn`, so references to captured variables can't escape the closure
error: could not compile `playground` due to previous error
I don't know how to constrain the closure's lifetime to the arguments.

Here's something that gets close:
use std::pin::Pin;
use std::future::Future;
#[macro_use]
extern crate derive_new;
#[derive(new)]
struct Test
{
}
impl Test
{
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where 'arg: 'test
{
*val0 + *val1
}
}
trait ClosureFn
{
fn call<'myself, 'arg>(&'myself self, v0: &'arg usize, v1: &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'myself>>
where 'arg: 'myself;
}
#[derive(new)]
struct Closure
{
test: Test
}
impl ClosureFn for Closure
{
fn call<'myself, 'arg>(&'myself self, v0: &'arg usize, v1: &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'myself>>
where 'arg: 'myself
{
Box::pin(async
{
self.test.fun(v0, v1).await
})
}
}
#[tokio::main(flavor = "current_thread")]
async fn main()
{
let test = Test::new();
let boxed: Box<dyn ClosureFn> = Box::new(Closure::new(test));
let v0 = 10;
let v1 = 20;
let ret = boxed.call(&v0, &v1).await;
println!("{ret}");
}
Unfortunatelly, you need to create the 'Closure' structure, and call the function via 'call'.

I was missing a move at the async function, I got confused by the compiler's error message:
use std::future::Future;
use std::pin::Pin;
fn constrain<Fun>(fun: Fun) -> Fun
where
Fun: for<'arg> Fn(&'arg usize, &'arg usize) -> Pin<Box<dyn Future<Output = usize> + 'arg>>,
{
fun
}
#[derive(Clone)]
struct Test {}
impl Test
{
pub async fn fun<'test, 'arg>(&'test self, val0: &'arg usize, val1: &'arg usize) -> usize
where
'arg: 'test,
{
*val0 + *val1
}
}
pub async fn fun<'arg>(val0: &'arg usize, val1: &'arg usize) -> usize {
val0 + val1
}
#[tokio::main(flavor = "current_thread")]
async fn main()
{
let test = Test{};
let boxed = Box::new(constrain(move |v0, v1|
{
let test = test.clone();
let ret = Box::pin(async move
{
test.fun(v0, v1).await
//fun(v0, v1).await
});
ret
}));
let v0 = 10;
let v1 = 20;
let ret = boxed(&v0, &v1).await;
println!("{ret}");
}
I found the solution here, it happened to someone else too:
https://users.rust-lang.org/t/lifetimes-issue-while-storing-rust-async-closure-functions-for-later-invocation/52232/2

Related

Borrow error when attempting recursion on HashMap, where each value needs a reference to the map

I'm currently have an issue regarding Rust's borrowing policy.
I have a HashMap of structs 'Value', each which contains a list of keys to other Values in HashMap. I am attempting to recursively call a function on these Values which requires a reference to the HashMap.
use std::collections::HashMap;
struct Value {
val: f64,
prevs: Vec<usize>,
sum: f64,
}
impl Value {
pub fn new(i: usize) -> Value {
let mut res = Value {
val: 0.1,
prevs: Vec::new(),
sum: 0.0,
};
for j in 0..i {
res.prevs.push(j);
}
res
}
pub fn evaluate(&mut self, pool: &mut HashMap<usize, Value>) -> f64 {
self.sum = self.val;
for i in &self.prevs {
let prev = pool.get_mut(i).unwrap();
self.sum += prev.evaluate(pool);
}
self.sum
}
}
fn main() {
let mut hm: HashMap<usize, Value> = HashMap::new();
for i in 0..10 {
hm.insert(i, Value::new(i));
}
println!("{}", hm.get(&9).unwrap().evaluate(&mut hm));
}
Error:
error[E0499]: cannot borrow `*pool` as mutable more than once at a time
--> src/lib.rs:25:39
|
24 | let prev = pool.get_mut(i).unwrap();
| --------------- first mutable borrow occurs here
25 | self.sum += prev.evaluate(pool);
| -------- ^^^^ second mutable borrow occurs here
| |
| first borrow later used by call
Playground
Context
I'm attempting to calculate the output of a neural network (usually done via feedforward) by starting from the output, and recursively evaluating each node, as a weighted sum of the nodes connected to it, with an unpredictable topology. This requires each node having a list of input_nodes, which are keys to a node pool HashMap.
Below is a sample with a few variants:
Non-performant and probably deadlock-prone but compiling version using Arc<Mutex>
High-performance version using Vec and split_at_mut
Highly unsafe, UB and "against-all-good-practices" version using Vec and pointers. At least evaluates to the same number, wanted to add for performance comparison.
#![feature(test)]
extern crate test;
use std::{collections::HashMap, sync::{Arc, Mutex}};
#[derive(Debug)]
struct Value {
val: f64,
prevs: Vec<usize>,
sum: f64,
}
impl Value {
pub fn new(i: usize) -> Value {
let mut res = Value {
val: 0.1,
prevs: Vec::new(),
sum: 0.0,
};
for j in 0..i {
res.prevs.push(j);
}
res
}
pub fn evaluate(&mut self, pool: &mut HashMap<usize, Arc<Mutex<Value>>>) -> f64 {
self.sum = self.val;
for i in &self.prevs {
let val = pool.get_mut(i).unwrap().clone();
self.sum += val.lock().unwrap().evaluate(pool);
}
self.sum
}
pub fn evaluate_split(&mut self, pool: &mut [Value]) -> f64 {
self.sum = self.val;
for i in &self.prevs {
let (hm, val) = pool.split_at_mut(*i);
self.sum += val[0].evaluate_split(hm);
}
self.sum
}
// OBS! Don't do this, horribly unsafe and wrong
pub unsafe fn evaluate_unsafe(&mut self, pool: *const Value, pool_len: usize) -> f64 {
let pool = std::slice::from_raw_parts_mut(pool as *mut Value, pool_len);
self.sum = self.val;
for i in &self.prevs {
let (pool_ptr, pool_len) = (pool.as_ptr(), pool.len());
self.sum += pool[*i].evaluate_unsafe(pool_ptr, pool_len);
}
self.sum
}
}
fn main() {
// arcmutex
let mut hm: HashMap<usize, Arc<Mutex<Value>>> = HashMap::new();
for i in 0..10 {
hm.insert(i, Arc::new(Mutex::new(Value::new(i))));
}
let val = hm.get(&9).unwrap().clone();
assert_eq!(val.lock().unwrap().evaluate(&mut hm), 51.2);
// split vec
let mut hm = (0..10).map(|v| {
Value::new(v)
}).collect::<Vec<_>>();
let (hm, val) = hm.split_at_mut(9);
assert_eq!((hm.len(), val.len()), (9, 1));
assert_eq!(val[0].evaluate_split(hm), 51.2);
}
#[cfg(test)]
mod tests {
use test::bench;
use super::*;
#[bench]
fn bench_arc_mutex(b: &mut bench::Bencher) {
let mut hm: HashMap<usize, Arc<Mutex<Value>>> = HashMap::new();
for i in 0..10 {
hm.insert(i, Arc::new(Mutex::new(Value::new(i))));
}
b.iter(|| {
let val = hm.get(&9).unwrap().clone();
assert_eq!(val.lock().unwrap().evaluate(&mut hm), 51.2);
});
}
#[bench]
fn bench_split(b: &mut bench::Bencher) {
let mut hm = (0..10).map(|v| {
Value::new(v)
}).collect::<Vec<_>>();
b.iter(|| {
let (hm, val) = hm.split_at_mut(9);
assert_eq!(val[0].evaluate_split(hm), 51.2);
});
}
#[bench]
fn bench_unsafe(b: &mut bench::Bencher) {
let mut hm = (0..10).map(|v| {
Value::new(v)
}).collect::<Vec<_>>();
b.iter(|| {
// OBS! Don't do this, horribly unsafe and wrong
let (hm_ptr, hm_len) = (hm.as_ptr(), hm.len());
let val = &mut hm[9];
assert_eq!(unsafe { val.evaluate_unsafe(hm_ptr, hm_len) }, 51.2);
});
}
}
cargo bench results to:
running 3 tests
test tests::bench_arc_mutex ... bench: 13,249 ns/iter (+/- 367)
test tests::bench_split ... bench: 1,974 ns/iter (+/- 70)
test tests::bench_unsafe ... bench: 1,989 ns/iter (+/- 62)
Also, have a look at https://rust-unofficial.github.io/too-many-lists/index.html

How do I calculate a multiple factorial using num_bigint in Rust?

I am trying to calculate a factorial of a factorial in Rust using the Num-BigInt library. I've gotten to the point where I can calculate a factorial:
use num_bigint::BigUint;
use num_traits::{One, Zero, FromPrimitive};
fn factorial(n: usize) -> BigUint {
let mut f: BigUint = One::one();
for i in 1..(n+1) {
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
f = f * bu;
}
f
}
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(5));
}
I want to do a double factorial, like:
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(factorial(5)));
}
However, this throws the following error because the data types are different:
error[E0308]: mismatched types
--> src/main.rs:16:30
|
16 | println!("{}", factorial(factorial(5)));
| ^^^^^^^^^^^^ expected `usize`, found struct `BigUint`
How can I repeat this function using BigUint instead of usize?
The problem is that you first want to use a usize and then a BigUint as your function parameter, while your parameter is set to be a usize.
To fix this you should make your factorial function generic and then only allow those types that make sense for your particular method.
I took your example and extended it to allow for all unsigned integer types:
use num_bigint::BigUint;
use num_traits::{One, FromPrimitive, Unsigned};
use num::{Integer, NumCast, ToPrimitive};
fn factorial<N: Unsigned + Integer + ToPrimitive>(n: N) -> BigUint {
let mut f: BigUint = One::one();
let end: usize = NumCast::from(n).unwrap();
for i in 1..(end + 1) {
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
f = f * bu;
}
f
}
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(factorial(5 as u32)));
}
This will however lead to not allowing factorial(5), because 5 is treated as an i32 by default, which can be signed. If you wish to allow for signed types and instead fail at runtime you can do something like that:
use num_bigint::BigUint;
use num_traits::{One, FromPrimitive};
use num::{Integer, NumCast, ToPrimitive};
fn factorial<N: Integer + ToPrimitive>(n: N) -> BigUint {
let mut f: BigUint = One::one();
let end: usize = NumCast::from(n).expect("Number too big or negative number used.");
for i in 1..(end + 1) {
let bu: BigUint = FromPrimitive::from_usize(i).unwrap();
f = f * bu;
}
f
}
pub fn main() {
println!("Starting calculation...");
println!("{}", factorial(factorial(5)));
}

How can I add functions with different arguments and return types to a vector?

I'm trying add functions with different arguments to a vector.
fn f1() {
println!("Hello, World!");
}
fn f2(s: &str) -> String {
String::from(s)
}
fn f3(i: i32) {
println!("{}", i);
}
fn main() {
let v = vec![f1, f3, f2];
}
But this gives the error:
error[E0308]: mismatched types
--> src/main.rs:12:22
|
12 | let v = vec![f1, f3, f2];
| ^^ incorrect number of function parameters
|
= note: expected type `fn() {f1}`
found fn item `fn(i32) {f3}`
Is there any way I can make this work?
The error happens because vectors are only meant to hold homogeneous data, i.e. every element of a vector has to be the same type. To solve this, you could for example use a vector of enums:
enum E {
F1(fn()),
F2(fn(&str) -> String),
F3(fn(i: i32)),
}
fn f1() {
println!("Hello, World!");
}
fn f2(s: &str) -> String {
String::from(s)
}
fn f3(i: i32) {
println!("{}", i);
}
fn main() {
let v = vec![E::F1(f1), E::F3(f3), E::F2(f2)];
for func in v {
match func {
E::F1(f) => f(),
E::F2(f) => println!("{}", f("foo")),
E::F3(f) => f(2),
}
}
}
Output
Hello, World!
2
foo
Or you could use a container made specifically for storing heterogeneous data, aka a tuple:
fn main() {
let v = (f1, f3, f2);
v.0();
v.1(2);
println!("{}", v.2("foo"));
}
Output
Hello, World!
2
foo

Most efficient way to fill a vector from back to front

I am trying to populate a vector with a sequence of values. In order to calculate the first value I need to calculate the second value, which depends on the third value etc etc.
let mut bxs = Vec::with_capacity(n);
for x in info {
let b = match bxs.last() {
Some(bx) => union(&bx, &x.bbox),
None => x.bbox.clone(),
};
bxs.push(b);
}
bxs.reverse();
Currently I just fill the vector front to back using v.push(x) and then reverse the vector using v.reverse(). Is there a way to do this in a single pass?
Is there a way to do this in a single pass?
If you don't mind adapting the vector, it's relatively easy.
struct RevVec<T> {
data: Vec<T>,
}
impl<T> RevVec<T> {
fn push_front(&mut self, t: T) { self.data.push(t); }
}
impl<T> Index<usize> for RevVec<T> {
type Output = T;
fn index(&self, index: usize) -> &T {
&self.data[self.len() - index - 1]
}
}
impl<T> IndexMut<usize> for RevVec<T> {
fn index_mut(&mut self, index: usize) -> &mut T {
let len = self.len();
&mut self.data[len - index - 1]
}
}
The solution using unsafe is below. The unsafe version is slightly more than 2x as fast as the safe version using reverse(). The idea is to use Vec::with_capacity(usize) to allocate the vector, then use ptr::write(dst: *mut T, src: T) to write the elements into the vector back to front. offset(self, count: isize) -> *const T is used to calculate the offset into the vector.
extern crate time;
use std::fmt::Debug;
use std::ptr;
use time::PreciseTime;
fn scanl<T, F>(u : &Vec<T>, f : F) -> Vec<T>
where T : Clone,
F : Fn(&T, &T) -> T {
let mut v = Vec::with_capacity(u.len());
for x in u.iter().rev() {
let b = match v.last() {
None => (*x).clone(),
Some(y) => f(x, &y),
};
v.push(b);
}
v.reverse();
return v;
}
fn unsafe_scanl<T, F>(u : &Vec<T> , f : F) -> Vec<T>
where T : Clone + Debug,
F : Fn(&T, &T) -> T {
unsafe {
let mut v : Vec<T> = Vec::with_capacity(u.len());
let cap = v.capacity();
let p = v.as_mut_ptr();
match u.last() {
None => return v,
Some(x) => ptr::write(p.offset((u.len()-1) as isize), x.clone()),
};
for i in (0..u.len()-1).rev() {
ptr::write(p.offset(i as isize), f(v.get_unchecked(i+1), u.get_unchecked(i)));
}
Vec::set_len(&mut v, cap);
return v;
}
}
pub fn bench_scanl() {
let lo : u64 = 0;
let hi : u64 = 1000000;
let v : Vec<u64> = (lo..hi).collect();
let start = PreciseTime::now();
let u = scanl(&v, |x, y| x + y);
let end= PreciseTime::now();
println!("{:?}\n in {}", u.len(), start.to(end));
let start2 = PreciseTime::now();
let u = unsafe_scanl(&v, |x, y| x + y);
let end2 = PreciseTime::now();
println!("2){:?}\n in {}", u.len(), start2.to(end2));
}

Two dimensional vectors in Rust

Editor's note: This question predates Rust 0.1 (tagged 2013-07-03) and is not syntactically valid Rust 1.0 code. Answers may still contain valuable information.
Does anyone know how to create mutable two-dimensional vectors in Rust and pass them to a function to be manipulated?
This is what I tried so far:
extern crate std;
fn promeni(rec: &[u8]) {
rec[0][1] = 0x01u8;
}
fn main() {
let mut rec = ~[[0x00u8,0x00u8],
[0x00u8,0x00u8]
];
io::println(u8::str(rec[0][1]));
promeni(rec);
io::println(u8::str(rec[0][1]));
}
You could use the macro vec! to create 2d vectors.
fn test(vec: &mut Vec<Vec<char>>){
vec[0][0] = 'd';
..//
vec[23][79] = 'd';
}
fn main() {
let mut vec = vec![vec!['#'; 80]; 24];
test(&mut vec);
}
Did you intend that all of the subarrays will have the length 2, as in this example? In that case, the type of the parameter should not be &[u8], which is a borrowed array of u8's, but rather &[[u8; 2]].
If the functions that is going to manipulate are yours, you can create a custom struct with the helper methods to treat the vector as 2d:
use std::fmt;
#[derive(Debug)]
pub struct Vec2d<T> {
vec: Vec<T>,
row: usize,
col: usize,
}
impl<T> Vec2d<T> {
pub fn new(vec: Vec<T>, row: usize, col: usize) -> Self {
assert!(vec.len() == row * col);
Self { vec, row, col }
}
pub fn row(&self, row: usize) -> &[T] {
let i = self.col * row;
&self.vec[i..(i + self.col)]
}
pub fn index(&self, row: usize, col: usize) -> &T {
let i = self.col * row;
&self.vec[i + col]
}
pub fn index_mut(&mut self, row: usize, col: usize) -> &mut T {
let i = self.col * row;
&mut self.vec[i + col]
}
}
impl<T: std::fmt::Debug> std::fmt::Display for Vec2d<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut str = String::new();
for i in 0..self.row {
if i != 0 {
str.push_str(", ");
}
str.push_str(&format!("{:?}", &self.row(i)));
}
write!(f, "[{}]", str)
}
}
fn main() {
let mut mv = Vec2d::new(vec![1, 2, 3, 4, 5, 6], 2, 3);
*mv.index_mut(1, 2) = 10;
println!("Display: {}", mv);
println!("Debug: {:?}", mv);
}
The associated function new creates the Vec2d, have two main methods (index and index_mut, so you can get a index value borrowed immut ou mut) and added a Display trait to visualise it better (but it is stored as Vec<>).

Resources