Picking the Right Tool for the Job
When your only tool is a hammer, every problem looks like a nail.
- Abraham Maslow
I recently organized a coding dojo where we solved the bowling kata. In short, the bowling kata is about programming a score-keeper for a game of ten-pin bowling. At any given time during the game, the score-keeper must be able to yield the current score for all players. Additionally, the program must be able to tell which player is the current player, in order to assign scores correctly.
I began solving the kata in my programming language of choice, C#. The solution naturally converged to an imperative state machine, incrementing scores as the game progressed. This lead to entangled code with many special cases, struggling with the tracking of arbitrary strikes and spares.
Then I realized that the problem is in fact two-fold. One part of the problem is to keep track of which player knocks over which pins, while the other part is the actual calculation of the scores. Given a sequence of numbers representing the amount of pins knocked over, the score can be calculated as a relatively simple function. At this point, I reached for my .NET toolbox and picked the tool best suited for writing functional code, F#.
module BowlingCalculator
[<CompiledNameAttribute("CalculateScore")>]
let calcScore pins =
let rec calcScore pins frame =
match pins with
// Strike with determined bonus
| 10 :: y :: z :: rest -> 10 + y + z + calcScore (y :: z :: rest) (frame + 1)
// Strike -without- determined bonus
| 10 :: y :: [] -> 0
// Spare with determined bonus
| x :: y :: z :: rest when x + y = 10 -> 10 + z + calcScore (z :: rest) (frame + 1)
// Spare -without- determined bonus
| x :: y :: [] when x + y = 10 -> 0
// Open frame
| x :: y :: rest -> x + y + calcScore (rest) (frame + 1)
// Special last frame
| x :: y :: z :: [] when frame = 10 -> x + y + z
// Otherwise
| _ -> 0
calcScore pins 1
If you are familiar with functional programming and pattern matching, the code above should be pretty obvious. I will not go into much depth explaining it, but suffice it to say that it is a recursive function traversing the list of pins knocked over, aggregating the score as it goes.
The rest of the program, responsible for keeping track of state, was kept in C#. After adding a reference to the F# module, calling into the calculating function is as simple as:
public class Player
{
private readonly List<int> pinsKnockedOver;
// snip...
public int CalculateScore()
{
var pins = ListModule.OfSeq(pinsKnockedOver);
return BowlingCalculator.CalculateScore(pins);
}
}
Both being first class .NET citizens, interoperability between C# and F# is a breeze. The only hitch at this point was that my F# function required an F# list as its argument, while the Player class uses a regular List<T> to keep track of the pins knocked over. ListModule.OfSeq() converts any IEnumerable<T> into an F# list, solving that problem with ease.
The complete source code is available on GitHub at https://github.com/tormodfj/katas/tree/master/mixed/Bowling.
In my opinion, this solution takes the best from two worlds, using the imperative C# for state tracking and the functional F# for calculations. Learning the functional paradigm is like acquiring a new tool in your toolbox, enabling you to view problems from other points of view.
Simple but Useful Extension Methods
In my previous post, I gave a fairly quick introduction to extension methods in C#. This post will present two examples to illustrate how readability can be improved by means of very simple extension methods.
One of the most common checks you perform on a string is whether it has any value. The string type has a static IsNullOrEmpty method intended for this purpose. The reason this method is static is that it could never check for null if it was an instance method. Rather, it would throw a NullReferenceException. Consider this extension method, however.
public static class Extensions
{
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
}
Being static, this method can be invoked even when value is null. But, due to the fact that it is defined as an extension method, you can invoke it using instance method syntax, improving readability.
string foo = null;
if(foo.IsNullOrEmpty())
{
// Do something
}
Another common scenario is parsing string values into corresponding enumeration values. Again, .NET provides a static method for this purpose. The Enum type has a static Parse method which takes a Type parameter and a string parameter, and returns an object which then has to be casted to the specified type.
string day = "Monday"; DayOfWeek dayOfWeek = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), day);
The signal-to-noise ratio of that second line of code is rather poor. Consider the following generic extension method.
public static class Extensions
{
public static T ToEnum<T>(this string value)
{
return (T)Enum.Parse(typeof(T), value);
}
}
Notice how this method does exactly the same as the concrete DayOfWeek example above. With this extension method in place, however, each parse operation can now be reduced to the following.
string day = "Monday"; DayOfWeek dayOfWeek = day.ToEnum<DayOfWeek>();
Again, the major benefit is with the readability.
The examples in this post are extremely simple, but they illustrate how easily you can improve readability by simply wrapping existing functionality in a reasonably named extension methods. For more handy extension methods, I recommend browsing through this StackOverflow thread:
http://stackoverflow.com/questions/271398/post-your-extension-goodies-for-c-net
Extension Methods in C#
Extension methods were introduced as a C# feature in version 3. An extension method is really nothing but a plain old static method. The difference is how you can invoke that static method. Conventionally, a static method is called by explicitly telling the compiler which class contains the method.
int absoluteValue = Math.Abs(-5);
Here, the static method Abs is called on the Math class with the argument -5. If the Abs method was declared an extension method, the first parameter could have been passed using instance method invocation syntax.
int absoluteValue = -5.Abs(); // Not valid
The most obvious place to find extension methods in .NET is in the LINQ namespaces. One such extension method is Enumerable.Where. Consider these two invocations of this method.
var values = new int[]{ 1, 2, 3, 4, 5 };
var filtered1 = values.Where(i => i < 3);
var filtered2 = Enumerable.Where(values, i => i < 3);
The two calls to Where are equivalent. In fact, the C# compiler will simply transform the former syntax into the latter before compilation. This transformation does require, however, that the compiler looks for a static method called Where in all static classes in all included namespaces, but this operation is reasonably fast.
Creating your own extension methods is very easy. The only requirements are that the method is static, its class is static and the first parameter of the method specifies a this keyword. Consider this example
public static class IntExtensions
{
public static bool IsEven(this int value)
{
return value % 2 == 0;
}
public static bool IsOdd(this int value)
{
return !value.IsEven();
}
}
These two extension methods will seemingly augment all ints with the two methods IsEven and IsOdd, making the following code compile.
if(2.IsEven() && 3.IsOdd())
{
Console.WriteLine("All is good");
}
Extension methods can drastically improve readability, especially when performing multiple operations. Consider these two lines of code.
Utils.DoSomethingElse(Utils.DoSomething(Utils.Transform(x, "arg1"), "arg2"));
x.Transform("arg1").DoSomething("arg2").DoSomethingElse();
There is no argument that the second line is much easier to interpret while reading than the first line. Extension methods make such a “chaining” syntax of static method calls possible.
Before you go bananas and convert all your static utility methods to extension methods, however, consider this warning from MSDN:
Extension methods are less discoverable and more limited in functionality than instance methods. For those reasons, it is recommended that extension methods be used sparingly and only in situations where instance methods are not feasible or possible.
In my next post, I will present a couple of simple but handy extension methods which can be useful in most any project.
Tail Recursion in C# and F#
For those of you who are unfamiliar with the notion of tail recursion, let me quote Wikipedia’s definition.
In computer science, tail recursion (or tail-end recursion) is a special case of recursion in which the last operation of the function, the tail call, is a recursive call
Tail recursion is essential in functional languages like F#, where iterative solutions are often implemented using recursion. If the recursion gets too deep, a stack overflow occurs, and your program crashes brutally. The rationale behind tail recursion is that if the recursive call is the last operation of the function, the stack frame of the current function invocation can be discarded before the recursive function invocation is made.
Rather than spending too much time discussing programming theory, let me present two equivalent programs, both containing tail recursion.
C#
class Program
{
static int n = 1000000;
static void Countdown()
{
if (0 > n--) return;
Countdown();
}
static void Main(string[] args)
{
Countdown();
Console.WriteLine("Done");
}
}
F#
let n = 1000000
let rec countdown n =
match n with
| 0 -> ()
| _ -> countdown (n-1)
countdown n
printfn "Done"
These two programs are semantically equivalent. They both use tail recursion to count from 1 000 000 to zero, before writing “Done” to the console.
Let us first look at the F# solution. Apart from being precise and easy to comprehend, it actually works. In fact, the F# compiler is smart enough to optimize the countdown function into a simple while loop, producing MSIL equivalent to the following C# code:
public static void countdown(int n)
{
while (true)
{
switch (n)
{
case 0:
return;
}
n--;
}
}
But what about the tail recursive C# solution? While tail recursion optimization has been proposed to Microsoft, the current C# compiler does nothing of the kind. Hence, the resulting MSIL contains a recursive Countdown method. The question is then: “Will the C# solution result in a stack overflow?” Interestingly, the answer is: “It depends.”
It turns out, if you compile the C# code with “Platform target: Any CPU” and run it on a 64-bit version of the Microsoft .NET runtime, the JIT compiler will actually perform tail recursion optimization from the MSIL itself, resulting in a working program. If, however, you compile with “Platform target: x86″ or run the program on a 32-bit version of the Microsoft .NET runtime, a stack overflow occurs. This behavior is described in the blog post “Tail call JIT conditions” by David Broman. Basically, the feature sets of the 64-bit and 32-bit versions of the JIT compiler do not coincide.
So, unless you are 100 % certain that your C# application will run on the 64-bit runtime, do no employ tail recursion with the intent of preventing stack overflows. Then again, if you are writing imperative C# code, tail recursion will probably not cross your mind as the best solution to any of your problems.