2014-09-21 63 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