Rust中某个结构的惯用迭代器+突变?

道格

我刚写完这段代码:

/// 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可能匹配数百个文件,但是我只关心文件树中的唯一路径,以便可以将它们绑定到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);
  }
}

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章