gpt4 book ai didi

rust - Rust 结构上的惯用迭代器 + 突变?

转载 作者:行者123 更新时间:2023-11-29 08:08:10 28 4
gpt4 key购买 nike

我刚刚写完这段代码:

/// Watcher to look for changes in files
pub struct Watch<'a> {
glob:Option<Glob>,
ruv:Vec<*mut c_void>,
paths:Vec<Path>,
pub callback:Option<|Path, WatchEvent|: 'a>
}

impl<'a> Watch<'a> {

/// Start watching for changes in any of the files matching known patterns
pub fn watch(&mut self, path:&str) {
let g = self.glob.take().unwrap();
for path in g.iter(path) {
match self.add_unique(&path) {
Some(p) => { self.bind(&path); },
None => {}
}
}
self.glob = Some(g);
}

/// Check for a matching path
fn add_unique(&mut self, path:&Path) -> Option<Path> {
let mut found = false;
for i in self.paths.iter() {
if i.as_str().unwrap().as_bytes() == path.dirname() {
found = true;
break;
}
}
if !found {
self.paths.push(Path::new(path.dirname()));
return Some(Path::new(path.dirname()));
}
return None;
}

...

}

我特别不高兴必须将 glob 移出 Watch 实例,以便我可以迭代路径匹配并更新对象的状态。

我尝试了几种方法,但所有其他替代方案都涉及创建临时向量,这是完全不可行的(glob 可能匹配数百个文件,但我只关心文件树中的唯一路径,以便它们可以绑定(bind)到 libuv 的文件事件 api;我绝对不想创建一个包含每个匹配文件的巨大列表的矢量)。

如何将其写成更地道的形式?

我觉得使用函数调用可以大大简化它,但它的确切语义让我难以理解。

本质上,我要在这里实现的是:

for every filename in g.iter(path)
if the path of the filename is not known yet
call bind() on the path
save the filename so future calls to watch() dont duplicate watch it

这是一个带有虚拟数据的围栏,显示了它的运行情况:http://is.gd/09wYTS

编辑:这就是为什么我必须将 Glob 移到 iter() 上:http://is.gd/FGlmw5

最佳答案

在我看来,这是迭代器失效的典型问题。您正在尝试修改正在迭代的结构。当用 C++ 编写时,它可以编译,但可能会发生“神奇”的事情。

处理这种情况的惯用方法是为要插入的项目创建临时结构,然后将它们插入到 for 循环之外。

沿线的东西:

pub fn watch(&mut self, path:&str) {
let temp = Vec::new();
for path in self.glob.iter(path) {
match self.would_add_unique(&path) {
Some(p) => { self.bind(&p); temp.push_back(&p); },
None => {}
}
}

for item in temp.iter() {
self.add_unique(&item);
}
}

或者您可以重新设计您的结构,使它们不再充当单一值。

关于rust - Rust 结构上的惯用迭代器 + 突变?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25960318/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com