Change:
It calls on a vector repeatedly. Example: and are directories with that many files in them. Theoretically this wants a deque.
Would keeping an index be sufficient? Just return and bump each time. It seems to me we don't need any fancy data structure. I can work on this.
That might work, but it does mean that the size of the internal vector grows to be the total number of elements ever touched, rather than just the number of children of recently-walked directories. It would also require cloning each of them. (Maybe not, if it stored internally and returned ...)
What about this. When we run out of space at the end, check if we are using more than half of the vector. If we are, allocate a new one at least twice as large. If we are not, swap all the values to the beginning of the vector. This way we have amortized linear time without needing to use a full blown deque. On Apr 10, 2014 2:14 AM, "Huon Wilson" wrote:
If you can get that to work, I guess so. But really, it would be better/more correct to just use a proper ... if std had access to one.
I am going to guess that taking out of std is undesirable. I can't really think of another way to do this rather than creating a simple . I'll work on it if you think this is acceptable.
"It calls .shift on a vector repeatedly." but it's very slow. Vec/Str need an efficient way to shift() multi-items
This isn't multiple items, it needs to shift the s off one at a time.
( I would be OK with moving deque into a "secret" module inside std and reexporting it from libcollections, however rustdoc doesn't support this nicely just yet.)
How about something along these lines: I didn't test the above, removing syntax errors is left as an exercise to the reader. Edit: Never mind, I see this changes the order that walk_dir guarantees. I'll try and rewrite my proposal tonight to make it emulate the current behaviour.
I'm not sure the current order is important, I don't know though (if it's not important we can probably just use as a stack, which is efficient). However, if we wish to retain the current order, I really do think the correct solution is to just use a deque, rather than write a complicated specialised data structure for this relatively simple task. (Unless that data structure has other significant benefits, of course. Maybe avoiding the copies from each vec to main deque will be noticably more efficient?)

Discussion:
/// Returns an iterator which will recursively walk the directory structure /// rooted at `path`. The path given will not be iterated over, and this will <del> /// perform iteration in a top-down order. </del> <ins> /// perform iteration in some top-down order.  The contents of unreadable /// subdirectories are ignored. </ins> pub fn walk_dir(path: &Path) -> IoResult<Directories> { Ok(Directories { stack: try!(readdir(path)) }) }

impl Iterator<Path> for Directories { fn next(&mut self) -> Option<Path> { <del> match self.stack.shift() { </del> <ins> match self.stack.pop() { </ins> Some(path) => { if path.is_dir() { match readdir(&path) {

check!(rmdir(dir)); }) <ins> iotest!(fn file_test_walk_dir() { let tmpdir = tmpdir(); let dir = &tmpdir.join("walk_dir"); check!(mkdir(dir, io::UserRWX)); let dir1 = &dir.join("01/02/03"); check!(mkdir_recursive(dir1, io::UserRWX)); check!(File::create(&dir1.join("04"))); let dir2 = &dir.join("11/12/13"); check!(mkdir_recursive(dir2, io::UserRWX)); check!(File::create(&dir2.join("14"))); let mut files = check!(walk_dir(dir)); let mut cur = [0u8, .. 2]; for f in files { let stem = f.filestem_str().unwrap(); let root = stem[0] - ('0' as u8); let name = stem[1] - ('0' as u8); assert!(cur[root as uint] < name); cur[root as uint] = name; } check!(rmdir_recursive(dir)); }) </ins> iotest!(fn recursive_mkdir() { let tmpdir = tmpdir(); let dir = tmpdir.join("d1/d2");