SpanMode uses incorrect terminology (breadth)

Ben Davis entheh at cantab.net
Mon Sep 17 16:28:07 PDT 2012


I have a feeling most people have missed the point here. Thanks for the 
example - it's a good one to work with. The 'expected approximation' was 
a bit of a mix of traversal strategies, so I've snipped it out below and 
put my own examples. Hope this helps clarify what I was getting at:

On 17/09/2012 06:30, Jesse Phillips wrote:
>
>> What would be an example illustrating that "breadth" is doing the
>> wrong thing?
>>
>> Andrei
>
> Linux 64bit:
>
> import std.file;
> import std.stdio;
>
> void main() {
>      mkdir("a");
>      mkdir("a/b");
>      mkdir("a/c");
>      mkdir("a/c/z");
>      std.file.write("a/1.txt", "");
>      std.file.write("a/2.txt", "");
>      std.file.write("a/b/1.txt", "");
>      std.file.write("a/b/2.txt", "");
>      std.file.write("a/c/1.txt", "");
>      std.file.write("a/c/z/1.txt", "");
>      foreach(string file; dirEntries("a/", SpanMode.breadth))
>          writeln(file);
>
>      rmdirRecurse("a");
[snip]

Here are the CORRECT tree traversal patterns:

Breadth-first (probably never required):
a/b
a/c
a/1.txt
a/2.txt
a/b/1.txt
a/b/2.txt
a/c/z
a/c/1.txt
a/c/z/1.txt
Defining property: number of /'s increases monotonically. Note how the 
deeper you go, the more spread out the children become. It's ALL 
children, then ALL grandchildren, then ALL great-grandchildren, etc.

I wouldn't bother implementing breadth-first. It's doubtful that anyone 
would want it, surely...?

Depth-first search has two useful variants, preorder and postorder.

Preorder depth-first (currently wrongly called SpanMode.breadth):
a/b
a/b/1.txt
a/b/2.txt
a/c
a/c/z
a/c/z/1.txt
a/c/1.txt
a/1.txt
a/2.txt
Defining property: every directory is immediately followed by all its 
children.

Postorder depth-first (currently only called SpanMode.depth):
a/b/1.txt
a/b/2.txt
a/b
a/c/z/1.txt
a/c/z
a/c/1.txt
a/c
a/1.txt
a/2.txt
Defining property: every directory is immediately *preceded* by all its 
children.

Going back to the 'actual' output you quoted:

>      // Actual
>      // a/c
>      // a/c/z
>      // a/c/z/1.txt
>      // a/c/1.txt
>      // a/b
>      // a/b/2.txt
>      // a/b/1.txt
>      // a/2.txt
>      // a/1.txt

This looks like a preorder depth-first iteration (albeit with child 
order reversed at each level). The implementation is correct in that it 
matches the spec as documented. The problem is that the spec is using 
the term 'breadth' wrongly.

Here is what I would do to fix it (sorry if I got the syntax wrong):

enum SpanMode {
   shallow,
   preorder,
   postorder;

   @deprecated alias preorder breadth;
   @deprecated alias postorder depth;
}

I initially said that possibly preorder and postorder weren't clear, but 
they grew on me very quickly. I think people could learn that "preorder 
means parents first" or "preorder is the one I usually want". Also, 
these are the standard terms (refer to the Wikipedia link), so once you 
know them, you can use them for everything, both in and outside of :D.

Thanks,

Ben :)


More information about the Digitalmars-d mailing list