I'm trying to implement a generator for the following recursive code that generates the sample locations in a multidimensional grid:
struct SampleDomain {
pub min: f64,
pub max: f64,
pub n_seg: i32, // number of segments
}
impl SampleDomain {
pub fn values(&self) -> Vec<f64> {
let step = (self.max - self.min) / (self.n_seg as f64);
(0..=self.n_seg).step_by(1).map(|p| self.min + (p as f64) * step).collect()
}
}
struct Lattice {
pub cube: Vec<SampleDomain>,
pub value: Vec<f64>,
}
fn main() {
let domains = vec![
SampleDomain { min: -2.0, max: -1.0, n_seg: 2 },
SampleDomain { min: -1.0, max: -0.0, n_seg: 4 },
SampleDomain { min: 0.0, max: 1.0, n_seg: 5 },
SampleDomain { min: 1.0, max: 2.0, n_seg: 2 },
];
let mut lattice = Lattice {
cube: domains,
value: vec![-2.0, -1.0, 0.0, 1.0], // initial sample location
};
grid_points(0, &mut lattice);
}
fn grid_points(n: usize, lattice: &mut Lattice) {
if n == lattice.value.len() {
println!("{:#?}", lattice.value);
return
}
for i in lattice.cube[n].values() {
lattice.value[n] = i;
grid_points(n + 1, lattice);
}
}
How can I implement this in a generator so that I can iterate:
fn main() {
// ... as before
for gp in grid_points(0, &mut lattice) {
println!("Gp: {:#?}",gp);
}
}
I've been studying the genwaiter
package but have problems using recursion with async
. This is how far I've got:
fn main() {
let domains = vec![
SampleDomain { min: -2.0, max: -1.0, n_seg: 2 },
SampleDomain { min: -1.0, max: -0.0, n_seg: 4 },
SampleDomain { min: 0.0, max: 1.0, n_seg: 5 },
SampleDomain { min: 1.0, max: 2.0, n_seg: 2 },
];
let mut lattice = Lattice {
cube: domains,
value: vec![-2.0, -1.0, 0.0, 1.0],
};
let lattice = RefCell::new(lattice);
for v in gen_lattice(0, lattice) {
println!("Lattice: {:#?}", v);
}
}
fn gen_lattice(n: usize, lattice: RefCell<Lattice>) -> GenBoxed<Vec<f64>> {
Gen::new_boxed(|mut co| {
async move {
let lat = lattice.borrow_mut();
if n == lat.value.len() {
co.yield_(lat.value.clone()).await;
}
for i in lat.cube[n].values() {
lat.value[n] = i;
gen_lattice(n + 1, lattice);
}
}
})
}
...producing the following err msg:
Compiling genawaiter v0.99.1 (/home/hjansen/workspace/gitspace/Simtryx/projects/following/language-specific/rust/generators/genawaiter)
error: future cannot be sent between threads safely
--> examples/recursion_HJ_3.rs:91:5
|
91 | Gen::new_boxed(|mut co| {
| ^^^^^^^^^^^^^^ future created by async block is not `Send`
|
= help: the trait `std::marker::Sync` is not implemented for `std::cell::Cell<isize>`
note: future is not `Send` as this value is used across an await
--> examples/recursion_HJ_3.rs:97:16
|
94 | let lat = lattice.borrow_mut();
| --- has type `std::cell::RefMut<'_, Lattice>` which is not `Send`
...
97 | co.yield_(lat.value.clone()).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ await occurs here, with `lat` maybe used later
...
104 | }
| - `lat` is later dropped here
= note: required by `genawaiter::sync::boxed::<impl genawaiter::sync::Gen<Y, R, std::pin::Pin<std::boxed::Box<(dyn std::future::Future<Output = C> + std::marker::Send + 'static)>>>>::new_boxed`
Help much appreciated!