2014-09-21 59 views
2

我刚刚结束了写这个代码: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可能会匹配数百个文件,但我只关心文件树中的唯一路径,以便他们可以被绑定到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

编辑:这里就是为什么我有移动水珠出到iter():http://is.gd/FGlmw5

回答

2

正如我所看到的,这是迭代器失效的典型问题。你正试图修改你正在迭代的结构。当用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); 
    } 
} 

或者你可以重新设计你的结构,使他们不作为单个值。

+0

不够公平。我并不是很乐意创建一个任意的临时向量(可能很大),但我想这比移动一个值更好。 – Doug 2014-09-23 00:31:43