救各大神们指教
我有使用了 toml 的库 程式码依赖
[dependencies]
toml = "0.8.19"
目的:我想写一个简单的 TOML
小工具,当写了 a.b.c
且给了 true
应该会呈现出以下。
[a.b]
c = true
完整程式码如下:
use toml::{Table, Value};
fn edit(mut_table: &mut Table, path: Vec<&str>, value: Value) {
// 简单的一个操作,path 有 n 个元素 keys 的长度会是 n-1
// ex: path = ["a", "b", "c"] 则 keys = ["a", "b"]
let keys = path[..path.len() - 1]
.into_iter()
.map(|&x| (*x).to_string());
// 定义 current 让之后可以定位到内层的树状结构
let mut current = mut_table;
// 遍历键路径,逐步定位到最内层的表格
for key in keys {
current = match current.get_mut(&key) { // -------------------------------------- - Err 可变引用第一次
// 如果目标表格中已有该键,则获取其对应的值,并定位到其位置
Some(Value::Table(t)) => t,
Some(_) => unimplemented!(), // 假设 path[..n-1] 路径一定是 Table 不会是其他的
// 如果目标键不存在,则创建一个"新表格",并让这个"新表格"作为其位置
None => {
// 在此 key 建立表
current.insert(key.clone(), Value::Table(Table::new())); // -------- Err 可变引用第二次
// 取到刚刚的 key 指向的表
target.get_mut(&key).unwrap().as_table_mut() // ------------------- Err 可变引用第三次
}
};
}
current.insert(path.last().unwrap().to_string(), value);
}
fn main() {
let mut t = Table::new();
let p = "a.b.c".split('.').collect::<Vec<&str>>();
let v = Value::Boolean(true);
edit(&mut t, p, v);
println!("{:?}", t.to_string());
}
讨论:
或许觉得不要用mut_table: &mut Table
去修该,直接用mut_table
所有权去改,可是就算是这样target.get_mut(&key)
这行所取得的一样是可变&mut Table
。
而且也不可能总是都获取有所有权吧,就这个例子确实只是去修该资料,也没做超出修改范围的行为,所以用 &mut Table
合理吧。
目前是查到可以用 Entry
来解决这个问题,但是个人认为不可能每次都依赖 Entry
要是库中没有提供!不就不能实现这样常见的逻辑了吗。
我喜欢 Entry
的解决逻辑,但不想依赖它,好像没它就办不了事了,可怕! !
for key in keys {
current = {
current
.entry(key)
.or_insert_with(|| Value::Table(Table::new()))
.as_table_mut()
.unwrap()
};
}
1
共 5 条评论, 1 页
评论区
写评论https://github.com/rust-lang/rfcs/pull/216
补一下 RFC, 里面可以看到,以前的 HashMap 是有
find_or_insert_with
这种内部修改的方法的。Entry API 就是设计出来解决你的问题的。
最早的 HashMap 是没有 Entry API 的,然后社区里的人觉得用着不顺手,不符合人体工程学, 于是集思广益设计了 Entry API, 满足了大伙对 Ergonomic 的追求。
所以正确的态度就应该是去用,去喷其他地方怎么没有这种 API, 怎么没有人体工程学的追求。
这是当前 borrowck 的限制, 下一代 borrowck 就是瞄着解决这个问题的, 但啥时候能 stable 就不知道了
--
👇
祐祐: 你好~感谢你的回覆,我再添加一点复杂的细节。
我想表达说在这种情况下是否有更好的作法,从这个例子可以看出来,调用一次
contains_key
查询又再调用get_mut
并没有特别好,相同的key
做查询需要两次,每当复杂性提一点(多查询一次key
),查询就要多一次,我不是有多要求性能,而是想寻找更好的作法,面对这样的规则约束,是否能有更通用的更漂亮的作法呢。--
👇
jerryshell
你好~感谢你的回覆,我再添加一点复杂的细节。
我想表达说在这种情况下是否有更好的作法,从这个例子可以看出来,调用一次
contains_key
查询又再调用get_mut
并没有特别好,相同的key
做查询需要两次,每当复杂性提一点(多查询一次key
),查询就要多一次,我不是有多要求性能,而是想寻找更好的作法,面对这样的规则约束,是否能有更通用的更漂亮的作法呢。--
👇
jerryshell