Rust 借用循环中使用的可变成员
我想解决的问题是: 给定递归嵌套的数据结构,例如JSON树和指向其中可能不存在的元素的路径,返回元素的可变引用,即最接近给定路径的引用 示例:如果我们有格式为{a:{b:{c:foo}}}的JSON文档和路径a.b.d,我们希望有一个指向存储在键b下的值的可变指针 这是一段代码片段,到目前为止我得到了: 使用std::collections::HashMap; 枚举Json{ 第64号, 布尔布尔, 弦, ArrayVec, ObjectHashMap } 结构指针{ 值:&'a mut Json,Rust 借用循环中使用的可变成员,rust,borrow-checker,Rust,Borrow Checker,我想解决的问题是: 给定递归嵌套的数据结构,例如JSON树和指向其中可能不存在的元素的路径,返回元素的可变引用,即最接近给定路径的引用 示例:如果我们有格式为{a:{b:{c:foo}}}的JSON文档和路径a.b.d,我们希望有一个指向存储在键b下的值的可变指针 这是一段代码片段,到目前为止我得到了: 使用std::collections::HashMap; 枚举Json{ 第64号, 布尔布尔, 弦, ArrayVec, ObjectHashMap } 结构指针{ 值:&'a mut Jso
路径:Vec我完全误解了你的问题,我应该向你道歉 您不能在一次传递中完成此操作-您需要执行只读传递以查找最近的路径或精确路径,然后执行读写传递以实际提取引用,或者以闭包的形式传递mutator函数 我为您提供了两次通过的方法。请注意,它仍然非常有效:
fn nearest_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Pointer<'a, 'b> {
let valid_path = nearest_path(obj, path);
exact_mut(obj, valid_path).unwrap()
}
fn exact_mut<'a, 'b>(obj: &'a mut Json, path: Vec<&'b str>) -> Option<Pointer<'a, 'b>> {
let mut i = 0;
let mut target = obj;
for token in path.iter() {
i += 1;
// borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
// this once-per-loop binding makes the scope clearer and circumvents the error
let target_once = target;
let target_opt = match *target_once {
Json::Object(ref mut map) => map.get_mut(*token),
Json::Array(ref mut list) => match token.parse::<usize>() {
Ok(t) => list.get_mut(t),
Err(_) => None,
},
_ => None,
};
if let Some(t) = target_opt {
target = t;
} else {
return None;
}
}
Some(Pointer {
path,
position: i,
value: target,
})
}
/// Return a mutable pointer to JSON element having shared
/// the nearest common path with provided JSON.
fn nearest_path<'a, 'b>(obj: &'a Json, path: Vec<&'b str>) -> Vec<&'b str> {
let mut i = 0;
let mut target = obj;
let mut valid_paths = vec![];
for token in path.iter() {
// borrow checker gets confused about `target` being mutably borrowed too many times because of the loop
// this once-per-loop binding makes the scope clearer and circumvents the error
let target_opt = match *target {
Json::Object(ref map) => map.get(*token),
Json::Array(ref list) => match token.parse::<usize>() {
Ok(t) => list.get(t),
Err(_) => None,
},
_ => None,
};
if let Some(t) = target_opt {
target = t;
valid_paths.push(*token)
} else {
return valid_paths;
}
}
return valid_paths
}
原理很简单——我重复了我在初始问题中编写的方法,以获得最近的有效路径或精确路径
从那里,我将它直接输入到我原始答案中的函数中,因为我确信路径在前面的函数调用中是有效的,所以我可以安全地展开:-使用一个额外的闭包参数,然后返回一个结果如何?虽然这是一个有趣的答案,但它并不完整-正如最近的名称所示目标不是返回与路径匹配的元素,但当没有匹配的元素时,返回最接近的元素-请阅读我在开头附上的示例。@BartoszSypytkowski编辑了道歉和一些新代码。感谢您指出,我完全错过了它