Home:ALL Converter>Better way to get tree representation of directory using F#?

Better way to get tree representation of directory using F#?

Ask Time:2014-12-01T15:32:06         Author:T Powers

Json Formatter

I am new(ish) to F# and am trying to get a tree representation of a filesystem directory. Here's what I came up with:

type FSEntry =
  | File of name:string
  | Directory of name:string * entries:seq<FSEntry>

let BuildFSDirectoryTreeNonTailRecursive path = 
  let rec GetEntries (directoryInfo:System.IO.DirectoryInfo) =
    directoryInfo.EnumerateFileSystemInfos("*", System.IO.SearchOption.TopDirectoryOnly)
    |> Seq.map (fun info -> 
        match info with 
        | :? System.IO.FileInfo as file -> File (file.Name)
        | :? System.IO.DirectoryInfo as dir -> Directory (dir.Name, GetEntries dir)
        | _ -> failwith "Illegal FileSystemInfo type"
        )

  let directoryInfo = System.IO.DirectoryInfo path
  Directory (path, GetEntries directoryInfo)

But... pretty sure that isn't tail recursive. I took a look at the generated IL and didn't see any tail prefix. Is there a better way to do this? I tried using an accumulator but didn't see how that helps. I tried mutual recursive functions and got nowhere. Maybe a continuation would work but I found that confusing.

(I know that stack-depth won't be an issue in this particular case but still would like to know how to tackle this non-tail recursion problem in general)

OTOH, it does seem to work. The following prints out what I am expecting:

let PrintFSEntry fsEntry =
  let rec printFSEntryHelper indent entry  =
      match entry with
      | File name -> printfn "%s%s" indent name
      | Directory(name, entries) ->
        printfn "%s\\%s" indent name
        entries 
        |> Seq.sortBy (function | File name -> 0 | Directory (name, entries) -> 1)
        |> Seq.iter (printFSEntryHelper (indent + "  "))

  printFSEntryHelper "" fsEntry

This should probably be a different question but... how does one go about testing BuildFSDirectoryTreeNonTailRecursive? I suppose I could create an interface and mock it like I would in C#, but I thought F# had better approaches.

Edited: Based on the initial comments, I specified that I know stack space probably isn't an issue. I also specify I'm mainly concerned with testing the first function.

Author:T Powers,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/27223613/better-way-to-get-tree-representation-of-directory-using-f
yy