Rust实现BSP树:简化节点归属侧判断函数的方法
优化后的实现方案
先直接给出简化后的代码:
use std::rc::Rc; enum Side { L = 0, R = 1, } enum RegionKind { Split { subregion: [Option<Rc<Region>>; 2], }, Client{ window: i32, }, } struct Region { kind: RegionKind, container: Option<Rc<Region>>, tags: u8, } impl Region { fn side(&self) -> Side { // 确保container存在,非法状态直接panic let container = self.container.as_ref().expect("Region must have a container"); // 强制匹配Split类型,非Split直接panic(符合业务假设) let RegionKind::Split { subregion, .. } = &container.kind else { panic!("Container region must be a Split variant"); }; // 遍历子区域数组,通过索引映射到Side subregion.iter() .enumerate() .find_map(|(idx, maybe_child)| { maybe_child.as_ref() // 用Rc标准方法比较指针同一性 .filter(|child| Rc::ptr_eq(child, self)) .map(|_| match idx { 0 => Side::L, 1 => Side::R, _ => unreachable!("Subregion array only has 2 elements"), }) }) // 确保当前节点是父节点的子节点,非法状态panic .expect("Region is not a child of its container") } }
针对两个问题的具体优化
1. 消除重复检查逻辑
- 使用
enumerate()遍历subregion数组的索引+元素,把两次重复的判断逻辑合并成一次迭代处理 - 用
find_map()同时完成"查找匹配项"和"映射为Side"的操作,彻底消除嵌套的match/if分支 - 替换手动
as_ptr()比较为Rc::ptr_eq(),这是Rust中比较Rc指针同一性的标准安全写法,语义更清晰
2. 处理不可达分支的问题
- 用
expect()替代as_ref()?,直接在container不存在时panic(符合你"所有Region都有container"的假设) - 使用Rust 1.65引入的else分支匹配语法,当
container.kind不是Split时直接panic,既满足编译器的类型要求,又明确标记该分支为非法状态(不可达) - 最后用
expect()兜底,确保当前节点确实是父节点的子节点,直接返回确定的Side类型(符合业务逻辑)
如果需要保留返回Option<Side>的容错空间,可调整为:
impl Region { fn side(&self) -> Option<Side> { let container = self.container.as_ref()?; let RegionKind::Split { subregion, .. } = &container.kind else { panic!("Container region must be a Split variant"); }; subregion.iter() .enumerate() .find_map(|(idx, maybe_child)| { maybe_child.as_ref() .filter(|child| Rc::ptr_eq(child, self)) .map(|_| match idx { 0 => Side::L, 1 => Side::R, _ => unreachable!(), }) }) } }
内容的提问来源于stack exchange,提问作者user21749640
相关产品推荐
相关产品推荐

