TextReader.TryReadLine And Idiomatic Code

Today I reread a post by Eric Lippert on High Maintenance code. It’s an interesting read in general, but some of the comments got me thinking about idioms in code. The discussion started with this bit of C#:

string line;
while ((line = reader.ReadLine()) != null)
    yield return line;

A familiar pattern in C and C++, but it just doesn’t feel right for C#. Eric cites this is a flaw “because it tries to do so much in one line.” His rewrite uses the following instead:

while (true)
{
    string line = reader.ReadLine();
    if (line == null)
        yield break;
    yield return line;
}

While certainly easier to read, it still seems like a lot of work. Commenter Sebastien Lorion suggests  this is a flaw in the API: “…we would not need such a hack or the awkward code you posted if the method was better designed.” I’m not sure I agree—ReadLine implies the line read will be returned, and if there’s nothing to read then nothing (null) should be returned. Sebastien’s “better design” doesn’t make sense idiomatically; what he really wants is TryReadLine, which would closely match his suggested signature of bool ReadLine(out string line). This strikes me as a perfect extension candidate:

public static bool TryReadLine(this TextReader reader, out string line)
{
    line = reader.ReadLine();
    return line != null;
}

With which we can write a more C#-idiomatic yet compact version of the original code:

public static IEnumerable<string> GetLines(this TextReader reader)
{
    string line;
    while (reader.TryReadLine(out line))
        yield return line;
}

Now one could argue whether or not TryReadLine() should catch the possible exceptions from ReadLine(), but that’s not the point. The point is that C# has an established pattern for methods that return a boolean indicating success in populating an out parameter, and code written as such is easier to read in a C# context.

It’s also interesting to note how the coding patterns can evolve with language features. For example, F# happens to have an Option type that aligns perfectly with this pattern: it either has Some value or is None. Paired with pattern matching, this presents a superior alternative to booleans and out parameters. So in idiomatic F# we would write TryReadLine like this instead:

namespace System.IO
    [<AutoOpen>]
    module TextReaderExtensions
        type System.IO.TextReader with
            member r.TryReadLine() =
                match r.ReadLine() with
                | null  -> None
                | line  -> Some line

Which could be used tail-recursively to fetch a sequences of lines:

            member r.Lines =
                let rec lines_core (tr : TextReader) =
                    seq {
                        match tr.TryReadLine() with
                        | None   -> yield! Seq.empty
                        | Some l -> yield l; yield! lines_core tr
                    }
                lines_core r

Eric ends his article with excellent advice: “Whenever you write a method think about the contract of that method.” As a corollary to that, whenever you write a method think about idioms that fit the method contract. An important part of maintainability is writing code that makes sense in the context of other code that has been written. Clever code that nobody can read isn’t particularly clever.

Advertisement
Posted in .NET, F#. Tags: . Comments Off on TextReader.TryReadLine And Idiomatic Code

Elegant Inline Debug Tracing

As much fun as it is to step through code with a debugger, I usually prefer to use System.Diagnostics.Debug and Trace with DebugView to see what’s happening in realtime. This is particularly handy to track intermediate results in higher-order functions that you might not be able to step into. However, it’s not always convenient to insert debugging statements amongst the composed expressions of F#, PowerShell or LINQ.

An alternative first came to mind while working in F#:

let dbg x = System.Diagnostics.Debug.WriteLine(x |> sprintf "%A"); x

(Read |> as “as next parameter to”.) We can then use this function anywhere to peek at a value, perhaps an intermediate list in this trivial example:

let data = [1..10]
           |> List.filter (fun i -> i%3 = 0) |> dbg
           |> List.map (fun i -> i*i)

Indeed [3; 6; 9] are traced as multiples of three. Not a particularly convincing example, but it should be pretty easy to imagine a more complex algorithm for which unintrusive tracing would be useful.

This works pretty well with F#’s |> operator to push values forward, but what about C#? Given my posting history, it shouldn’t be hard to guess where I’m going with this…

Extension Methods

So if |> is “as next parameter to”, the . of an extension method call might read “as first parameter to”. So we can implement a roughly equivalent function (sans F#’s nice deep-print formatter "%A") like so:

    public static T Debug<T>(this T value)
    {
        Debug.WriteLine(value);
        return value;
    }

    public static T Dbg<T>(this T value, string category)
    {
        Debug.WriteLine(value, category);
        return value;
    }

I find the optional label handy to keep different traces separate. Looking again, there’s an overload that accepts a category, so we’ll use that instead. So why might this be useful? Maybe we want to log the value assigned within an object initializer:

var q = new SPQuery() {
  Query = GetMyQuery().Debug("Query")
};

Rather than store the query string to a temporary variable or retrieve the property after it’s been set, we can just trace the value inline. Or consider a LINQ example:

var items = from SPListItem item in list.GetItems(q)
            let url = new SPFieldUrlValue(item["URL"] as string)
            where url.Url.Debug("URL").StartsWith(baseUrl, StringComparison.OrdinalIgnoreCase)
            select new
            {
                Title = item.Title.Debug("Title"),
                Description = url.Description,
            };

Here we log all URLs that pass through, even the ones excluded from the result by the predicate. This would be much harder to implement efficiently without inline logging.

This technique works great for simple objects with a useful ToString(), but what about more complex objects? As has often been the answer lately, we can use higher-order functions:

    public static T Dbg<T, R>(this T value, Func<T, R> selector)
    {
        Debug.WriteLine(selector(value));
        return value;
    }

    public static T Dbg<T, R>(this T value, string category, Func<T, R> selector)
    {
        Debug.WriteLine(selector(value), category);
        return value;
    }

Now we can provide a delegate to trace whatever we want without affecting the object itself. For example, we can easily trace a row count for the DataView being returned:

public DataView GetResults()
{
    var myTable = GetDataTable();
    // Process data...
    return myTable.DefaultView.Dbg("Result Count", v => v.Count);
}

I could go on, but you get the idea.

PowerShell Filter

Finally, we can implement similar functionality in PowerShell using a filter with an optional scriptblock parameter:

filter Debug([scriptblock] $sb = { $_ })
{
  [Diagnostics.Debug]::WriteLine((& $sb))
  $_
}

PS > 1..3 | Debug { $_*2 } | %{ $_*$_ }
1
4
9

Which traces 2, 4, 6, as expected.

Update 4/19/2009: Changed functions to use category overloads. And another point to consider: if the value being traced could be null, selector should be designed accordingly to avoid NullReferenceException. There’s nothing worse than bugs introduced by tracing or logging.