Creating a Lazy Sequence of Directory Descendants in F#

It seems to turn into a shoot-out: listing directories is suddenly en-vogue! 😃 So, Craig Andera posted this code in written in Clojure, which lists some directories lazily, and Chris Sells thought he could do that in C#, too. I thought these code examples all look rather verbose – in the case of Clojure because in that way rather typical for Java, the APIs are pretty verbose to use, and in the case of C# because of all the syntactic, well, ahem, necessities, as well as the fact that there’s no language feature for integrating nested sequences seamlessly. Keeping it nice and simple, in F# that example can look like this:

open System.IO

let rec GetDirectoryDescendants(path) =
    seq {
        yield! Directory.GetFiles(path)
        for subdir in Directory.GetDirectories(path) do
            yield! GetDirectoryDescendants(subdir)

For one thing, this code only contains what’s needed, like the Clojure code does – no namespaces, class declarations, loads of curlies, … nice. Second, the yield! statement. There’s also yield, without the !, in F#, and the difference is that while yield returns a single element for inclusion in the sequence, yield! takes an entire sequence and returns it one by one into the “upper level” sequence. You could argue that’s the same thing the C# code does as well, and you would be right, in a way. But the F# way is much shorter, more concise, and the code doesn’t break down again to the level of the sequence element.

Functional languages like these things – by using map instead of a for(each) loop, you have a well-known pattern to apply, and the reader of your code has to read less to see what exactly is going on. In the same way, by using yield! it is obvious what I’m doing without finding the code inside the foreach loop and confirming that all it does is, again, yield.

Sorry, this blog does not support comments.

I used various blog hosting services since this blog was established in 2005, but unfortunately they turned out to be unreliable in the long term and comment threads were lost in unavoidable transitions. At this time I don't want to enable third-party services for comments since it has become obvious in recent years that these providers invariably monetize information about their visitors and users.

Please use the links in the page footer to get in touch with me. I'm available for conversations on Keybase, Matrix, Mastodon or Twitter, as well as via email.