Creating a Lazy Sequence of Directory Descendants in C#
My dear friend Craig Andera posted an implementation of a function that descends into a directory in a “lazy” manner, i.e. you get the first descendant back right away and not after all descendants have been calculated. His implementation was in Clojure, a Lisp variant that runs on the Java VM:
(import [java.io File])
(defn dir-descendants [dir]
(let [children (.listFiles (File. dir))]
(lazy-cat
(map (memfn getPath) (filter (memfn isFile) children))
(mapcat dir-descendants
(map (memfn getPath) (filter (memfn isDirectory) children))))))
Craig was happy with this function because, even though it was a “mind-bender to write,” it’s easy to read and because C# “would almost certainly be at least somewhat more verbose.”
Taking this as a challenge, I rewrote this program in C#, maintaining the laziness:
using System.IO;
using System.Collections.Generic;
namespace ConsoleApplication1 {
class Program {
static IEnumerable
foreach (var file in Directory.GetFiles(path)) { yield return file; }
foreach (var directory in Directory.GetDirectories(path)) {
foreach (var file in GetDirectoryDecendants(directory)) { yield return file; }
}
}
}
}
The key hit here is the use of “yield return” which lets me return elements of an IEnumerable as I calculate them. This took me 5 minutes to write, my mind is straight and I find it fairly easy to read. I’ll let you decide on the relative verbosity of each implementation.