我如何 return 组合两个借来的 RefCells?

How can I return the combination of two borrowed RefCells?

我有一个结构,其中有两个 Vec 包裹在 RefCell 中。我想在该结构上有一个方法,该方法将两个向量组合在一起,并将它们 return 作为新的 RefCellRefMut:

use std::cell::{RefCell, RefMut};

struct World {
    positions: RefCell<Vec<Option<Position>>>,
    velocities: RefCell<Vec<Option<Velocity>>>,
}

type Position = i32;
type Velocity = i32;

impl World {
    pub fn new() -> World {
        World {
            positions: RefCell::new(vec![Some(1), None, Some(2)]),
            velocities: RefCell::new(vec![None, None, Some(1)]),
        }
    }

    pub fn get_pos_vel(&self) -> RefMut<Vec<(Position, Velocity)>> {
        let mut poses = self.positions.borrow_mut();
        let mut vels = self.velocities.borrow_mut();

        poses
            .iter_mut()
            .zip(vels.iter_mut())
            .filter(|(e1, e2)| e1.is_some() && e2.is_some())
            .map(|(e1, e2)| (e1.unwrap(), e2.unwrap()))
            .for_each(|elem| println!("{:?}", elem));
    }
}

fn main() {
    let world = World::new();

    world.get_pos_vel();
}

我如何 return 将矢量的压缩内容作为新的 RefCell?这可能吗?

我知道有 RefMut::map(),我尝试嵌套对 map 的两次调用,但没有成功。

如果你想 return 一个新的 Vec,那么你不需要将它包装在 RefMutRefCell:

根据您的代码 filtermap

pub fn get_pos_vel(&self) -> Vec<(Position, Velocity)> {
    let mut poses = self.positions.borrow_mut();
    let mut vels = self.velocities.borrow_mut();

    poses.iter_mut()
        .zip(vels.iter_mut())
        .filter(|(e1, e2)| e1.is_some() && e2.is_some())
        .map(|(e1, e2)| (e1.unwrap(), e2.unwrap()))
        .collect()
}

替代filter_map

poses.iter_mut()
    .zip(vels.iter_mut())
    .filter_map(|pair| match pair {
        (Some(e1), Some(e2)) => Some((*e1, *e2)),
        _ => None,
    })
    .collect()

你可以用 RefCell::new 将它包装在 RefCell 中,如果你真的想要的话,但我会把它留给函数的用户来包装它在他们需要的任何地方。

您希望能够修改位置和速度。如果这些必须存储在两个单独的 RefCell 中,那么 side-stepping 问题和使用回调进行修改呢?

use std::cell::RefCell;

struct World {
    positions: RefCell<Vec<Option<Position>>>,
    velocities: RefCell<Vec<Option<Velocity>>>,
}

type Position = i32;
type Velocity = i32;

impl World {
    pub fn new() -> World {
        World {
            positions: RefCell::new(vec![Some(1), None, Some(2)]),
            velocities: RefCell::new(vec![None, None, Some(1)]),
        }
    }

    pub fn modify_pos_vel<F: FnMut(&mut Position, &mut Velocity)>(&self, mut f: F) {
        let mut poses = self.positions.borrow_mut();
        let mut vels = self.velocities.borrow_mut();

        poses
            .iter_mut()
            .zip(vels.iter_mut())
            .filter_map(|pair| match pair {
                (Some(e1), Some(e2)) => Some((e1, e2)),
                _ => None,
            })
            .for_each(|pair| f(pair.0, pair.1))
    }
}

fn main() {
    let world = World::new();

    world.modify_pos_vel(|position, velocity| {
        // Some modification goes here, for example:
        *position += *velocity;
    });
}