LINQPad Dump for F#
If like me you’re a fan of LINQPad, you’ll be familiar with the
Dump method. This lets you easily output any value to the Results pane.
So if you had a C# LINQ expression like this:
"1,2,3,4,5,6" .Split(',') .Select(int.Parse) .Select(x => x * x) .Select(x => x.ToString()) .Aggregate("", (x,y) => x.Length == 0 ? y : x + "," + y) .Dump();
you’d see the following in the Results pane:
You can also attach a name to a call to
which gives you an output like this:
Even nicer is the fact that you can insert calls to
Dump at any point in the pipeline, which is great for debugging LINQ pipelines. So if we do this:
"1,2,3,4,5,6" .Split(',') .Select(int.Parse) .Dump("integers") .Select(x => x * x) .Dump("squares") .Select(x => x.ToString()) .Aggregate("", (x,y) => x.Length == 0 ? y : x + "," + y) .Dump("Result");
… then in the results pane we get the following nicely formatted output:
But can we use this in F#? If we try a naive conversion we find that we can’t use a named
Dump for our result, and we can’t insert calls to
Dump in the pipeline, as the F# compiler can’t easily be persuaded to select the correct overload. All we can do is pipe the final result into an unnamed
Dump. And that’s because
Dump really is a C# extension method, whose method signature is not a good fit for F# partial application.
"1,2,3,4,5,6" .Split(',') |> Seq.map int // |> Dump "integers" |> Seq.map (fun x -> x * x) // |> Dump "squares" |> Seq.map (sprintf "%d") |> String.concat "," |> Dump // "Result"
The good news is that we can make a couple of simple helper methods to restore the ability to use named dumps at any point. I’ve created one called
DumpAs, which can be placed at the end of your pipeline as it returns
unit, and one called
Peek which is designed to go in the middle of your pipeline, as it returns the input sequence unchanged:
let DumpAs (name:string) x = x.Dump name let Peek (name:string) x = x.Dump name x "1,2,3,4,5,6" .Split(',') |> Seq.map int |> Peek "integers" |> Seq.map (fun x -> x * x) |> Peek "squares" |> Seq.map (sprintf "%d") |> String.concat "," |> DumpAs "Result"
Hope someone finds this useful, and as always, let me know in the comments if there is a better way to solve this.
Definitely useful. Thanks!Robert Kerr
Simple but effective! Very useful, thanks.Mark Ashley Bell
Nice. Thanks. Just saved to MyQueries.Kevin McFarlane