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:
1,4,9,16,25,36
You can also attach a name to a call to Dump
:
.Dump("Result");
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.
Comments
Definitely useful. Thanks!
Robert KerrSimple but effective! Very useful, thanks.
Mark Ashley BellNice. Thanks. Just saved to MyQueries.
Kevin McFarlane