Navigate / search

The best job I’ve ever had

I found this old stream of consciousness recently. It had a special resonance as I prepared my talk for DDD North. I worked for a couple of Summers at the amazing TIC Summer Camp in Washington DC. It was the best job I ever had. It was also insanely hard, in the best possible way.

Memories of TIC
Still the best job I’ve ever had and I’ve given up hoping there’ll ever be a better one. My first year at TIC was my first time in the US. Karen picked me up at the airport. On the drive to her house I mentioned Visual Basic, and there and then in the car, the deal was done. We would be teaching Visual Basic. That’s how things work at TIC.

During my second year I suggested that computing and multi-media should be split with each having it’s own director. It was done. No arguing, no meetings, no debate. If someone suggested something and Karen couldn’t see a really good reason not to, she trusted the people she hired. For the Summer of ’96, there were two directors, and I was one of them.

And the campers, the amazing campers, teaching the Pythagorean theorem to a junior so his wrestlers could hit each other still stands out as a great memory.

The other staff, the lunch time chats, the nights out. Getting on the Metro one night with Martin Stephen’s like we’d done dozens of times before, but managing to go the wrong way, and ending up in the wrong part of town with no more trains to get us home, and managing to get home safe and sound anyway.

Being on what can just about be called a boat, in the middle of the Potomac, in the middle of the thunder storm, and realizing that if we sink, we’re taking most of the senior technical staff including two directors with us, but getting home safe and sound (if a little wet).

Swapping puzzles with Vasha Kristov, being led astray by John Mueller, Eating Fried Chicken after dark in Rock Creek Park with Adam Holt, being asked to leave by the Police. But getting home safe and sound.

Always getting home safe and sound.

If I could take one trip in a flying DeLorean, Washington DC in 1994 would be very tempting.

TIC Still exists, and has gone from strength to strength.

Curried vs Uncurried Functions

Over a year ago I explained Memoization in this post. If you’ve read that, you should be comfortable with the following.

open System.Collections.Generic

let negate x =
    printfn "Negating..."
    -x

let cache f =
    let cache = Dictionary<_, _>()

    fun x ->
        if cache.ContainsKey(x) then
            cache.[x]
        else
            let result = f x
            cache.[x] <- result
            result

let fastNegate = cache negate

We’re pretending that ‘negate’ is an expensive function that we want to avoid calling unnecessarily, so we use the ‘cache’ function to wrap ‘negate’ with some caching behaviour. Negate takes one argument. What happens when we try to cache a function that takes more than one argument, like ‘add x y’?

On first glance it appears to work.

let add x y = 
    printfn "Adding two args"
    x + y

let fastAdd = cache add

val add : x:int -> y:int -> int
val fastAdd : (int -> int -> int)

But if you try to use it the results are, disappointing.

> fastAdd 1 5;;
Adding two args
val it : int = 6

> fastAdd 1 5;;
Adding two args
val it : int = 6

The underlying ‘add’ function is called every time. We can check to see if anything is added to our cache with a ‘printfn’.

let cache f =
    let cache = Dictionary<_, _>()

    fun x ->
        if cache.ContainsKey(x) then
            cache.[x]
        else
            let result = f x
            cache.[x] <- result
            printfn "Added Item to cache, Items now in Cache: %d" cache.Count
            result

> fastAdd 1 2;;
Added Item to cache, Items now in Cache: 1
Adding two args
val it : int = 3

> fastAdd 1 2;;
Adding two args
val it : int = 3

> fastAdd 2 1;;
Added Item to cache, Items now in Cache: 2
Adding two args
val it : int = 3

That’s odd. The first time we call the function, something is added to the cache. The second time, using the same values, nothing is added to the cache. When we try different arguments another item is added to the cache. This suggests the cache is being used.

Remember that functions in FSharp are curried, which means that a function which takes two arguments (like add) is translated (curried) into a series of functions which each take a single argument.

So, when we try to cache

add x y

what we actually cache is the partially applied function

add x

We can test this. As long as we keep the same value for x, the fastAdd function will use the cached version. As soon as we change x, we get a new partially applied function that is different to the one in the cache. We can see this in the example above. It is the change in x from 1 to 2 that triggered the addition of a new item to the cache.

So, we’re not actually caching our *expensive* add function at all. We’re just caching the partial application of it.

We could rewrite our ‘add’ function so that it takes one argument, a tuple.

let add (x, y) =
    x + y

let fastAdd = cache add

> fastAdd (1, 2);;
Added Item to cache, Items now in Cache: 1
val it : int = 3

> fastAdd (1, 2);;
val it : int = 3

> fastAdd (1, 3);;
Added Item to cache, Items now in Cache: 2
val it : int = 4

We’ve ‘uncurried’ the function. Now everything works. But it’s still no good. We’ve duplicated our add function, and remember this all relates to functions that are a lot more complicated than addition.

We could wrap the original curried function so the logic isn’t duplicated. We’re really just putting an adapter around it to change it’s signature.

let add x y = 
    printfn "Adding two args"
    x + y

let uncurriedAdd (x, y) =
    add x y 

let fastAdd = cache uncurriedAdd

val add : x:int -> y:int -> int
val uncurriedAdd : x:int * y:int -> int
val fastAdd : (int * int -> int)

> fastAdd (1, 3);;
Adding two args
Added Item to cache, Items now in Cache: 1
val it : int = 4

> fastAdd (1, 3);;
val it : int = 4

That’s still rubbish though. The signature of ‘fastAdd’ is different to ‘add’, so it isn’t an alternative. If we think in terms of higher order functions, ‘add’ and ‘fastAdd’ have different types. We can’t pass ‘fastAdd’ to a function that is expecting ‘add’ and expect things to just work.

We could write a ‘cache2’ function that follows the same pattern as ‘cache’ but works with functions of two arguments. That will work but it’s a shame not to use the working cache function that we already have.

Feel free to stop reading and figure out a solution. What follows is one way of doing it.

The solutions above weren’t good enough, but we were on the right track. Uncurrying the ‘add’ function to make it compatible with our cache is fine, although we shouldn’t have to write a specific function each time we need to uncurry a function. Through the magic of higher order functions we can write the following.

let uncurryTwoToOne f (x, y) = f x y

That allows us to write the following.

let uncurriedAdd = uncurryTwoToOne add

That saves us doing the uncurrying individually for each function. It still leaves us with a function that isn’t compatible with the original signature of Add. So, caching it is still no good. Remember the ‘cache’ function doesn’t change the signature, it takes a function that accepts one argument and it wraps it to add caching, but it maintains the same signature. That way, the cached version can be used anywhere the original is used.

It looks like we need to wrap the cached version of ‘add’ in yet another function to convert the signature back to curried form. Another higher order function to the rescue.

let curryOneToTwo f x y = f (x, y)

And now we finally have a working solution.

let fastAdd = add |> uncurryTwoToOne |> cache |> curryOneToTwo

> fastAdd 1 3;;
Adding two args
Added Item to cache, Items now in Cache: 1
val it : int = 4

> fastAdd 1 3;;
val it : int = 4

Note that in the ‘fastAdd’ function we are not piping the result of ‘add’ through the chain of functions, the actual ‘add’ function itself is the value. Each function in the chain is passed a function which it wraps before passing it on. Like building up the layers of an onion.

It seems like we should be able to make ‘fastAdd’ into a general purpose higher order function too.

let curried2 f = f |> uncurryTwoToOne |> cache |> curryOneToTwo

Putting it all together. We get the following

open System.Collections.Generic

let uncurryTwoToOne f (x, y) = f x y

let curryOneToTwo f x y = f (x, y)

let cache f =
    let cache = Dictionary<_, _>()

    fun x ->
        if cache.ContainsKey(x) then
            cache.[x]
        else
            let result = f x
            cache.[x] <- result
            printfn "Added Item to cache, Items now in Cache: %d" cache.Count |> ignore
            result

let cache2 f = f |> uncurryTwoToOne |> cache |> curryOneToTwo

let add x y = 
    printfn "Adding two args"
    x + y

let fastAdd = cache2 add

> fastAdd 1 3;;
Adding two args
Added Item to cache, Items now in Cache: 1
val it : int = 4

> fastAdd 1 3;;
val it : int = 4

> fastAdd 1 4;;
Adding two args
Added Item to cache, Items now in Cache: 2
val it : int = 5

> fastAdd 1 4;;
val it : int = 5

Playing for a Draw

It’s September, so time for a small diversion from the technical stuff to something far more important, Hurling.

Prior to 2012 the last All-Ireland final to end in a draw was the 1959 Kilkenny Waterford final. Since 2012 all three finals have had to be replayed. This many draws in a row is wildly unusual, but that in itself isn’t evidence of funny business. Anomalies happen, that’s why we call them anomalies.

Hurlers are operating at levels of strength, skill and fitness unlike anything we have ever seen. If we assume that the top teams are reaching roughly the same heights, aren’t close games more likely? and consequently shouldn’t we see more draws?

Or is there more to it?

This year alone, Kilkenny and Tipperary ended level after normal time in the National Hurling League Final, and Kilkenny were only a point ahead after extra time. Kilkenny and Galway tied the Leinster Semi-Final, Clare and Wexford couldn’t be separated in Normal or Extra time in the Qualifiers, and their replay also went to extra time. And of course Sunday’s Epic also ended all square.

For as long as I can remember there have been suspicions that the GAA hope for draws and the revenue boost that replays provide. It’s quite possible that’s true, but it’s a leap from that to suggest that the GAA actively influence referees to blow up level games, or allow close games to run on a little longer in the hopes of the trailing team equalizing.

I’m sure referees would be extremely unhappy and would absolutely refuse to be influenced in such a way, and I don’t believe it happens.

I do however think referees are doing exactly what I described above, albeit at their own volition rather than in response to pressure. I believe they are stopping tied games as quickly as possible, but allowing close games to run on. Giving the trailing team “A chance”.

Exhibit A – All-Ireland Final – Kilkenny vs Galway – 9 September 2012
3 minutes of injury time were added, with Kilkenny leading by a point.
At 71.50 a free was given to Galway and Jackie Tyrell was booked moments after a trip on Kilkenny’s Tommy Walsh was ignored. Galway tied the score from the resulting free and the referee ended the game a second or two short of the end of injury time.

Exhibit B – All-Ireland Final – Cork vs Clare – 8 September 2013
2 minutes of injury time were added. When the two minutes have elapsed Cork are up by a point. The Referee allows play to continue for 27 seconds. Clare equalize and play is then stopped.

Exhibit C – League Final – Kilkenny vs Tipperary – 4 May 2014
3 minutes of injury time added. Kilkenny a point up when the 3 minutes have elapsed. Play is allowed to continue for 38 seconds, including a missed free to Tipperary. Tipperary equalize from play, the referee doesn’t allow the puckout. Normal time ends level.

In Extra-Time 1 minute of injury time is added. Kilkenny lead by a point when the 1 minute elapses. Referee allows the puckout, Kilkenny win the ball and the game is ended. We of course can’t know if Tipperary would have been allowed a few seconds to equalise if they had won the ball, but the pattern from other games suggests they might.

Exhibit D – Leinster Semi-Final – Kilkenny vs Galway – 22 June 2014
2 minutes of injury time added. Kilkenny score with 2 seconds of injury time remaining to lead by a point.
Play is allowed to run on for 21 seconds, Commentator makes the comment “He has to give them a chance”. Galway equalize and the game ends.

Exhibit E – All-Ireland Final – Kilkenny vs Tipperary – 9 September 2014
1 minute of injury time added. Sides are level, a questionable free is awarded to Tipperary. The incident is similar to the free awarded in the 2012 final between Kilkenny and Galway, but this time the free is given to the defending player rather than the player with the ball. Had the free been given to Kilkenny it would almost certainly have been scored.

The entire 1 minute of injury time is used up taking the free and waiting for a decision from Hawkeye, play resumes with 71 minutes 23 seconds on the clock yet no additional time is played after the puckout. The referee ends the game immediately, with the sides level.

What’s going on?
I don’t believe there is a conspiracy to create draws for the GAA, but I do believe the referees are taking the easy way out by giving teams “a chance” to equalize, or blowing up if the sides are level. The pattern of this happening in the past makes it harder for a referees in the future.

Solution
There has apparently already been a decision to implement a public clock for hurling. That should happen urgently.

Tied championship games should always go to extra time. At the moment there’s a bizarre situation where a League game or a Qualifier game can go to extra time, but other championship games including the All-Ireland final is an immediate replay if the sides are level and the end of normal time.

Of course, hurling games need never go to a replay. Simply allowing tied teams to play on until someone scores would end most games within minutes. Perhaps requiring a team to lead by two points to clinch a game would be fairer, and should still end the game with very little extra time.

I don’t think the GAA try to engineer draws, but I suspect the likelihood of them ever eliminating them is fairly remote.

Aim for DRY, but be willing to fall short.

I’m not going to rehash the reasons why “Don’t repeat yourself” (DRY) is a good thing, I’ll assume you know why duplicating code is bad.

Strictly speaking DRY isn’t really about repeating code, it’s more about representing the same “Information” or “Knowledge” in different places. For that to happen the code doesn’t actually have to be the same.

Conversely, duplicated code doesn’t always represent duplicated knowledge or information, completely different concepts can sometimes be represented by virtually identical code.

Mathias Verraes recently wrote a really good blog post on this very issue, it’s well worth a look.

This post is about aiming for DRY, but deliberately coming up short.

I’ve been adding some NUnit tests to an existing system recently and I kind of liked the way they turned out, despite the fact that I duplicated some code.

The following is heavily modified code, I can’t show the original, but it gets the point across. Please don’t read into anything you see about credentials or security, this code is one step away from Widgets and Wotzits, it’s NOT REAL CODE.

    class Describe_Club_Membership
    {
        [Test]
        public void A_User_Can_Join_The_Club()
        {
            UsingCredentials("appName", "appKey");
            var userId = GetUserId("someUsersEmail@example.com");

            EnsureUserIsNotAMember(userId)

            JoinClub(userId);
            Assert.That(IsAMember(userId));
        }

        [Test]
        public void A_User_Can_Leave_The_Club()
        {
            UsingCredentials("appName", "appKey");
            var userId = GetUserId("someUsersEmail@example.com");

            EnsureUserIsAMember(userId)

            LeaveClub(userId);
            Assert.That(IsNotAMember(userId));
        }

The entire contents of the tests are written using functions that exist only for the purpose of making the tests readable. In a sense these few functions define a Domain Specific Language. Code within any function (but particularly within a test) should always be written at the same level of Abstraction, would should never have code like the following in a test.

    class Describe_Club_Membership
    {
        [Test]
        public void A_User_Can_Join_The_Club()
        {
            var credentialsFactory = new CredentialsFactory("Membership");
            var credentials = credentialsFactory.CreateDefaultCredentials("appName", "appKey");

            var registrationRepo = new RegistrationsRepository(credentials);
            var userId = registrationRepo.GetUserByEmail("someUsersEmail@example.com").FirstOrDefault().Id;

            var binding = new BasicHttpBinding();
            var membershipEndPoint = new EndpointAddress(ConfigurationManager.AppSettings["..."]);
            
            var membershipService = new MembershipServiceClient(binding, membershipEndPoint);

            ... etc...   
        }

You get the idea, everything that needs to be done, is in the test, from pulling information out of Repositories, to reading Configuration Files, to configuring services endpoints to actually calling services, and on and on.

I don’t know about you, but I prefer the first code sample to the second.

Those functions that make up the Domain Specific Language in the first tests, have to go somewhere, and as you can see from the second example, some of them involve a little bit of work. Look again at the first code sample, you’ll see that I have a function called ‘UsingCredentials’ but it doesn’t return credentials. If it did I could pass them into the subsequent functions that need credentials, but in my DSL it’s enough to state the credentials I want to use. Passing the credentials and all the other dependencies around would unnecessarily clutter up the tests.

So, clearly the credentials are being saved somewhere by the ‘UsingCredentials’ function and then subsequent functions can use them.

    class Describe_Club_Membership
    {
        private Credentials _credentials;

        [Test]
        public void A_User_Can_Join_The_Club()
        {
            UsingCredentials("appName", "appKey");
            var userId = GetUserId("someUsersEmail@example.com");

            EnsureUserIsNotAMember(userId)

            JoinClub(userId);
            Assert.That(IsAMember(userId));
        }

        // Test Fixture DSL Commands
        private void UsingCredentials(string appName, string appKey)
        {
            _credentials = CredentialsHelper.GetCredentials(appName, appKey);            
        }

        ...

The UsingCredentials function is actually just a one liner, the heavy lifting is done elsewhere in a helper class. The job of getting credentials may be needed by lots of TestFixtures so I want that logic in a shared component, not duplicated. We’re heading in the right direction of DRY.

So, what then is the point of the UsingCredentials function we see here?

Put simply, I like the way it makes the tests read. I could have used this one liner, and others like it in the test, but a test made up of a series of these kinds of calls is more cluttered and it gives the impression that these helper classes may be significant to the test. I don’t want to give that impression.

I want to declutter the test so that only the logic being tested remains. Wrapping this and other one liners in tiny DSL style commands sends a message that the details of how the helpers are called is not as important than the logic being tested.

But what then if I want to use the same Helper from other Test Fixtures, aren’t I going to have to duplicate the little functions that wrap the one liners?

Yes I am.

This is where I deliberately fall short of DRY.

For one of my fixtures I have 7 of these tiny functions. They vary in complexity but none contain more than one line of code. Code that I do not want to see directly in my tests. In another fixture, I use three of those same wrapper functions, and I’ve duplicated the three that I need.

How could I make use of these DSL functions without duplicating them? One benefit of the wrapper functions is that they can access the credentials or any other member of the fixture without it being passed as a dependency. If I move the wrapper functions out I’m basically back to calling the helper functions and needing to pass all dependencies. In short, the wrapper functions no longer serve any purpose.

I could define the helpers and the credentials in a base class and inherit my test fixtures from that. That is in fact a really nice solution, it’s DRY, the Tests look just as nice and the Test Fixtures don’t even have the tiny wrapper functions in them.

If you wanted to go with the inheritance option I’d be hard pushed to make a case against it. I just don’t like inheritance and I really don’t like it in test suites.

Irrational as it may be I prefer to have these tiny functions so my tests can be as clean as possible, but I’m willing to fall a little short of DRY rather than use inheritance.

If someone is curious when looking at a test and wants to see what a function does or where credentials come from, it’s right there, in the fixture, no climbing an inheritance hierarchy.

As soon as you start using inheritance it sucks you in, you start adding more to the base class, or an extra level of inheritance here and there. It gets messy real fast.

What will happen when not all of the test Fixtures need Credentials? When some subset of fixtures need some other shared member? The Base class starts to become the union of all needs rather than the intersection. And for what? So we can avoid duplicating a handful of one line functions that are unlikely to change. Even if they do change it’s going to be trivial, perhaps a new argument to the helper function.

The key points for me are:

  1. Keep your tests as free of clutter as possible, nothing should remain but the logic being tested, written at a consistent level of abstraction.
  2. If necessary define a tiny Domain Specific Language for your tests as simple one liner functions which call to the real shared code, kept elsewhere.
  3. Keep the DSL functions you need right there in the Test Fixture, duplicate them if necessary. Don’t try to over engineer your DSL using inheritance or any other clever tricks.

The third point about inheritance is maybe up for debate, but I don’t thing the first two points are.

One Less Thing To Worry About

In the closing scene of the movie Forrest Gump, we learn that Lt. Dan helped Forrest invest in some kind of “Fruit” company (Apple Corp.).

“So then I got a call from him, saying we don’t have to worry about money no more. And I said, that’s good! One less thing.”

That quote comes to mind whenever I think about immutability.

Let’s make a list of Int’s and display it.

    var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    Console.WriteLine(string.Concat(numbers));

    Result: 123456789

Now, let’s reverse the list. In CSharp lists are mutable so we can do the following:

	var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	numbers.Reverse();
    Console.WriteLine(string.Concat(numbers));

    Result: 987654321

If we just wanted to show the numbers in reverse order, but keep the underlying list in order, this wouldn’t work. The Reverse method screws with our underlying data. The following would be nice.

	var rev = numbers.Reverse();

It’d be great if rev now pointed to a reversed list while numbers was still in order. That would be how an Immutable List would work, the Reverse method wouldn’t change anything, it would create a new List.

The result of the List object does the same, if you Sort, you sort the underlying data, you don’t get a new list. Add or Remove items, you change the underlying list.

There is a solution. There is an ImmutableList, just find Microsoft.Bcl.Immutable in Nuget and use System.Collections.Immutable, and you’re all set.

Except that’s a little problematic too. You lose that nice initialisation syntax that the old mutable list had.

	var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };

Under the hood CSharp relies on mutability to make that magic work.

So, you need to use NuGet and you need to write extra code, and all to stop you accidentally mutating a list. This is never going to be the default choice for CSharp developers.

IEnumerable
There is another choice, if we call the Reverse method as follows, we get the behavior we want.

	 rev = numbers.AsEnumerable().Reverse();

Problem solved. Well no. There’s an even bigger problem. Thanks to Jonas Elfström for writing up this post on IEnumerable.

Take a look at this code and see if you can figure out where the result comes from.

    var numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    var rev = numbers.AsEnumerable().Reverse();
    numbers.Reverse();
    Console.WriteLine(string.Concat(rev));
    Console.ReadKey();

    Result: 123456789

As Enumerable isn’t really giving you immutable behavior. The variable ‘rev’ is still pointing to the same underlying data, just through the lens of a lazy operation. The AsEnumerable().Reverse() won’t happen until we use the results. Which means reversing the underlying numbers will cause them to be reversed back again when we eventually use the IEnumerable view of it.

This is why I would prefer data structures that are immutable by default. You avoid this kind of silliness. I’m sure many will have no problem whatsoever with the example above, but I find it annoying, unintuitive and confusing.

In CSharp I never get to put mutability aside as one less thing to worry about. You have to work really hard to make anything immutable, really immutable.

There is a place for mutable data structures and a place for immutable data structures. It seems logical to me that if one has to be harder work than they other, immutable should be the easier of the two. It should be the default.

The challenge today is overwhelming complexity

Here’s a really great post by Tom Moertel on squeezing every last ounce of performance out of machines back in the day.

It was a time when unrolling a loop to save the few clock cycles or seeing a unique way to use the registers of a chip could take a game from clunky to classic.

Stories of making machines do the impossible are the stuff of legend. The closest we mere mortals came was rejigging our config.sys and autoexec.bat files to free up a little memory. If you’re under 30 even that may sound alien.

Tom’s post is a great read, but there is a real gem of wisdom towards the end, under the heading “To the old days!”.

“The challenge wasn’t overwhelming complexity, as it is today. The challenge was cramming your ideas into machines so slow, so limited that most ideas didn’t fit.”

Turn that quote around. The challenge today isn’t cramming your ideas into machines so slow so limited that most ideas don’t fit. The challenge today is overwhelming complexity.

The challenge today isn’t cramming your ideas into machines so slow so limited that most ideas don’t fit. The challenge today is overwhelming complexity.

I would guess that at this point less than 5% of developers ever need to sacrifice maintainability for performance. I’m probably being generous at that. If you are taking on complexity in order to speed up the execution of a method, or reduce it’s memory footprint, you’re more likely doing harm for no good reason.

But, this post isn’t about code. It’s all too easy to focus on “Clean Code”, have code reviews, refactor relentlessly etc. But, if you deploy that code into an overly complex environment, or using an unnecessarily complex infrastructure, or manage the whole thing using unnecessarily complex ceremony then your code cleaning efforts may be wasted.

It’s interesting how many books are available on how to write “good code”, or how to refactor “bad code”, but there are relatively few if any books about refactoring “bad environments”.

Refactoring should extend to the entire development process. If you can refactor away an unneeded Class, but can’t get rid of an unneeded tool, you’re on the road to ruin. No amount of intention revealing Interfaces or SOLID code will save you.

The phrase “Technical Debt” has been coined to mean the deliberate taking on of subpar “code”, with a view to fixing that problem later. I don’t believe it’s a satisfactory definition.

All too often “Technical Debt” means “We have this one line fix, we’ll come back later and implement it correctly in all of the Controllers, Views and Models that should be affected. I wonder about the logic of treating a change in multiple places as preferable to making a change in one place.

I also wonder whether that one liner change is where time will be lost in maintenance. Even if there is a more “correct” way of fixing an issue, is the code really where your team is losing productive hours?

Or, is it the time needed to set up a development environment? Or figure out how to find a test environment that’s “close enough” to production to be useful. Perhaps you have so many tools that nobody really understands how everything fits together any more.

If there is a “Knack” to getting your code base to build, then clean code is the least of your problems.

When the complexity of the solution exceeds the complexity of the problem, THAT’s technical debt. By “solution” I mean the WHOLE package. Code, Tools, Frameworks, Process, Infrastructure, Documentation, Planning, Review.

Very few of us need to find “clever” solutions any more. The capabilities of machines far exceed almost anything we could possibly want to do. The challenge now is complexity and we should be devoting a lot more of our attention to it.

Active Patterns : Choices and Nesting

And so, we arrive at the last post of the series. I’ll show you the F# ‘Choice’ type and show how it relates to active patterns. I’ll explain how to add additional parameters to a multi-case active pattern, and introduce some complex pattern matching using nested active patterns.

Look Ma! No Params
In the previous post I mentioned that Multi-Case active patterns can’t accept additional arguments beyond the one that all active patterns must accept. Here’s what the code might look like if they could.

let (|Smaller|Equal|Bigger|) (compareWith: int) (n: int) =
    if n < compareWith then Smaller
    elif n > compareWith then Bigger
    else Equal

let DescribeNumber (n: int) =
    match n with
    | Smaller 10 -> "Small"
    | Bigger 10 -> "Bigger"
    | Equal 10 -> "Equal"

On the face of it that looks like reasonable code. To see why it’s invalid, let’s change the DescribeNumber function slightly.

let DescribeNumber (n: int) =
    match n with
    | Smaller 5 -> "Small"
    | Bigger 10 -> "Bigger"
    | Equal 10 -> "Equal"

Assuming we could do this, what should happen if we pass the number 7 to DescribeNumber?

The first clause won’t match, because 7 is not smaller than 5. The second and third clauses won’t match either because 7 isn’t bigger than or equal to 10. So, we’ve taken a multi-case pattern, where they whole point is the completeness of the pattern matching, and we’ve broken that completeness by parameterizing each clause separately.

If you try this code out you’ll find that the error isn’t in the Pattern Recognizer, it’s in DescribeNumber. In other words, it’s fine to define a multi-case active pattern, as long as you don’t try to pattern match on it. That offers us a clue as to how to proceed.

let (|SmallerThan10|EqualTo10|BiggerThan10|) = (|Smaller|Equal|Bigger|) 10

If we partially apply the Active Pattern, locking in a value for the additional parameter, we’re back to a multi-case active pattern with one parameter. And our pattern match now looks like this.

let DescribeNumber (n: int) =
    match n with
    | SmallerThan10 -> "Small"
    | BiggerThan10 -> "Bigger"
    | EqualTo10 -> "Equal"

The original function has the values Smaller, Equal and Bigger and the partially applied version has SmallerThan10, EqualTo10 and BiggerThan10. Which begs the question, how does one map to the other? Is it just their positions?

Well, yes, that’s exactly how it works, but for an interesting reason that explains a lot about Multi-Case Active Patterns. Go back and take a look at the signature of the original active pattern.

val (|Smaller|Equal|Bigger|) :
  compareWith:int -> n:int -> Choice<unit,unit,unit>

It returns a Choice

Give me Choice
Just as the Option type allowed us to write functions that can return either ‘Some value’ or ‘None’. The Choice type allows us to return one of up to seven values (remember that seven item limit on multi-case active patterns?).

Forget about Active Patterns for a moment and look at this plain old function.

let Divide (by: int) (this: int) =
    if by = 0 then Choice1Of3 "You can't divide by zero, are you mad?"
    elif this % by = 0 then Choice2Of3 (this/by)
    else Choice3Of3 (decimal this/decimal by)

It’s type is as follows

val Divide : by:int -> this:int -> Choice<string,int,decimal>

Depending on the numbers you try to divide, this function will return one of three choices. A string (an error message for divide by zero), an int (numbers divide evenly), or a decimal (doesn’t divide evenly.)
We can pattern match on this function just like we do with Multi-Choice Active Patterns.

let DescribeDivide (this: int) (by: int) =
    match Divide this by with
    | Choice1Of3 error -> error
    | Choice2Of3 n -> sprintf "%d divides evenly by %d and the result is %d" this by n
    | Choice3Of3 n -> sprintf "%d doesn't divide evenly by %d and the result is %f" this by n

It may be starting to dawn on you now that the Multi-Case Active Pattern is a way of assigning names to those choices. In fact, if you take any function that takes a single argument and returns a Choice you can turn it into a Multi-Case Active Pattern, and call the various possibilities anything you like.

The following example partially applies the Divide function, the result is a Choice which can be turned into a multi-choice active pattern, and used immediately in a pattern match, all within a single function.

let DescribeDivide (by: int) (this: int) =
    let (|ByZero|Evenly|NotEvenly|) = Divide by
    match this with
    | ByZero error -> error
    | Evenly n -> sprintf "%d divides evenly by %d and the result is %d" this by n
    | NotEvenly n -> sprintf "%d doesn't divide evenly by %d and the result is %f" this by n

With all that in mind look again at the partially applied Multi-Case Active Pattern from above.

let (|SmallerThan10|EqualTo10|BiggerThan10|) = (|Smaller|Equal|Bigger|) 10

The signature of the original Active Pattern is

compareWith:int -> n:int -> Choice<unit,unit,unit>

Partially applying it we get a new function with the following signature

int -> Choice<unit,unit,unit>

One input parameter, and the out put is a Choice Of 3, so we can assign this to any Multi-Case Active Pattern name as long as it has 3 cases, in our example (|SmallerThan10|EqualTo10|BiggerThan10|).

Code Quotations
For this final example I need a reasonably elaborate domain model. Instead of creating a phony one, I’m going to use F# itself. Code Quotations provide a model for working with F# code as Data. The point of this example is to convey that even after 8 posts explaining Active Patterns in detail, there is still enormous scope to combine and use Active Patterns in interesting ways.

let model = <@ fun (x: int) -> x * x @>
val model : Expr<(int -> int)> = Lambda (x, Call (None, op_Multiply, [x, x]))

The quoted expression is a lambda that takes an integer x and squares it. The quotation determines that we have an int->int expression. Without getting too bogged down in the syntax, you should be able to see that it’s a Lambda that accepts a variable x and calls a multiply operation, passing two arguments, both of which are x.

OK, now you’re up to speed on Code Quotations, or as up to speed as you’re going to get from this post. It might be worth having a quick read of this page before continuing.

Here are some Namespaces we’ll make use of.

open Microsoft.FSharp.Quotations
open Microsoft.FSharp.Quotations.Patterns
open System.Reflection

That Patterns namespace will come in handy. Code Quotations come with a set of ready made Active Patterns. The following example uses two supplied patterns. ‘Call’ matches method calls, and ‘Value’ matches values. Both are Single Partial Active Patterns.

let rec Describe (expr: Expr) =
    match expr with
    | Call (_,f, left :: right :: []) -> sprintf "%s %s %s" (Describe left) f.Name (Describe right)
    | Value (v, t) when t.Name = "Int32" -> sprintf "%A" v
    | _ -> "?"

This function matches on method calls and values. It will fail to match on any other expression. The Call active pattern returns a three part tuple. We don’t care about the first part, the second part is the function that is called, which we bind to the name f. The third part of the tuple contains the list of arguments. We’ll match on calls that have exactly two arguments, and we bind them to the names left and right.

We’ll also match on values. The Value Active Pattern returns a tuple containing the value and the type. We bind the names v and t to those respectively, and we’ll only match if the type is ‘Int32’.

We add printing of the results and we get the following.

let desc = Describe <@ 2 - 1 * 5 - 3 @>
val desc : string = "2 op_Subtraction 1 op_Multiply 5 op_Subtraction 3"

OK, it ain’t pretty, but hopefully you can see how the Active Patterns are working. If we throw something other than integers at it, we won’t match the values.

let desc = Describe <@ 2.0 - 1.0 * 5.0 - 3.0 @>

val desc : string = "? op_Subtraction ? op_Multiply ? op_Subtraction ?"

Nesting
Now let’s have some fun. We’ll need to create two Active Patterns.

let (|MethodWithName|_|) (s:string) (m: MethodInfo) =
    if s = m.Name then Some() else None

let (|TypeWithName|_|) (s:string) (t: System.Type) =
    if s = t.Name then Some() else None

The first pattern accepts a string and a MethodInfo and matches if the method has the name we provide. The second does the same, but with the name of a Type.

Here’s where things get interesting, the second element of the Tuple returned by the Call Active Pattern is a MethodInfo, which means we can pass it to this new Active Pattern. Like this.

let rec Describe (expr: Expr) =
    match expr with
    | Call (_,MethodWithName "op_Multiply", [left; right]) -> sprintf "%s %s %s" (Describe left) "*" (Describe right)
    | Call (_,MethodWithName "op_Subtraction", [left; right]) -> sprintf "%s %s %s" (Describe left) "-" (Describe right)
    | Value (v, TypeWithName "Int32") -> sprintf "%A" v
    | _ -> "?"

We’ve nested a match on specific method names within matches on method Calls. This will now only match on calls to op_Multiply and op_Subtract. Knowing this we can describe the methods with their operators ‘*’ and ‘-‘ rather than the ugly full method names.

I did the same with the ‘TypeWithName’ active pattern and removed the ‘When’ clause in the process.
Let that sink in. You can use an active pattern to match on values returned from another active pattern. You don’t need a whole separate ‘match .. with’ expression.

I’ve only scratched the surface of nested types, for a much more detailed discussion this talk by Ross McKinlay is heavy going in places but really showcases the power of Active Patterns.

That’s all folks
That’s it for this series. I hope you found it worthwhile. We’ve covered an enormous amount of information. If you’ve managed to work through the entire series of posts you should be fully comfortable with Active Patterns. All that remains is the put them to good use.

Thanks for reading.

Active Patterns: Multi-Case (|A|B|)

Playing Cards are a commonly used example of discriminated unions in FSharp. I’m not presuming that you already understand Discriminated Unions, but I’m also not going to explain them. You should be able to follow along and get a sense of how they work. If you’d like to read up on them try here.

A Rank is something that can have one of 13 values Ace through King. A Suit can have one of 4 values Hearts, Clubs, Diamonds or Spades. A Card can be represented as a Tuple of Rank and Suit.

type Rank = Ace|Two|Three|Four|Five|Six|Seven|Eight|Nine|Ten|Jack|Queen|King
type Suit = Hearts|Clubs|Diamonds|Spades
type Card = Rank * Suit

As a brief aside take a look at the ‘*’ which indicates a tuple. Tuples are known as ‘product types’ their range of values are the product of the ranges of values of the types that make them up.

Let me try that again in English. 13 Ranks * 4 Suits = 52 Cards. I’ll pretend Jokers don’t exist, this series is long enough already.

(Two, Clubs)
(Queen, Hearts)
(Ace, Spades)

Cards have an interesting characteristic, every single one of them is either Red or Black. So, here’s a little challenge. Using what you’ve learned so far, write a function takes a card and returns a message like the following

(Two, Clubs) -> "The Two of Clubs is Black"
(Queen, Hearts) -> "The Queen of Hearts is Red"
(Ace, Spades) -> "The Ace of Spades is Black"

If you’re having trouble with that the following easier version will get you a passing grade.

(Two, Clubs) -> "Black"
(Queen, Hearts) -> "Red"
(Ace, Spades) -> "Black"

There are lots of ways we can approach this using the Single Active Patterns (both the Total and Partial varieties). All have drawbacks of one kind or another.

Single Total

Here’s how we could do it with a Single Total Active Pattern

let (|Red|) (card: Card) =
    match card with
    | (_, Hearts) | (_, Diamonds) -> true
    | _ -> false

let DescribeCard (card: Card) =
    match card with
    | Red true -> sprintf "Red" 
    | Red false -> sprintf "Black"

That’ll get us the passing grade but it’s pretty lousy. Black has vanished as a concept, all we have is “Not Red”, and within our match expression we’ve lost the details of the card, all we have is the boolean that tells us if it’s Red or not.

Partials
We can do better with two partials.

let (|Black|_|) (card: Card) =
    match card with
    | (_, Clubs) | (_, Spades) -> Some card
    | _ -> None

let (|Red|_|) (card: Card) =
    match card with
    | (_, Hearts) | (_, Diamonds) -> Some card
    | _ -> None

let DescribeCard (card: Card) =
    match card with
    | Black (rank, suit) -> sprintf "The %A of %A is Black" rank suit 
    | Red (rank, suit) -> sprintf "The %A of %A is Red" rank suit 

That’s better, but if you try that example you’ll see FSharp throws a warning in the DescribeCard function. It claims that we have an incomplete match pattern. FSharp is concerned that a card might come along that doesn’t match either Black or Red.

We know we’ve got our bases covered, but the use of Partials hides that fact from FSharp. What happens if a card comes along that gets ‘None’ from both (|Black|) and (|Red|). I knew those damn Jokers would bite us in the ass.

We could throw in a dummy catch all case that would get rid of the warning, but where’s the fun in that?

This, as it happens is an ideal scenario for a Multi-Case Active Pattern. We know that the full range of possible values for a card (i.e. all 52 cards) must map to one of a small set of possibilities (Red and Black). We can make that fact explicit using a Multi-Case active pattern and kill off a compiler warning in the process.

Multiple

let (|Red|Black|) (card: Card) =
    match card with
    | _,Hearts|_,Diamonds -> Red card
    | _ -> Black card

let DescribeCard (card: Card) =
    match card with
    | Red (rank, suit) -> sprintf "The %A of %A is Red" rank suit
    | Black (rank, suit) -> sprintf "The %A of %A is Black" rank suit

The partials are gone. There’s no more ‘Some card’ or ‘None’. Every card is classified as either a ‘Black card’ or a ‘Red card’. Our match expression doesn’t throw a warning any more because FSharp can understand that Red and Black are the Only possibilities for cards, and we handle them both.

Bringing It All Together
Let’s finish with a nice meaty example that brings together the various types of pattern we’ve covered. We’ll use Single and Multiple Active Patterns to pattern match and describe a hand of Blackjack cards. To keep things simple Ace will count as 11 only, it won’t also count as 1.

The points attached to each card are determined by the Rank. We’ll start with a function that scores a card.

let CardScore (card: Card ) = 
    match fst card with
    | Two -> 2
    | Three -> 3
    | Four -> 4
    | Five -> 5
    | Six -> 6
    | Seven -> 7
    | Eight -> 8
    | Nine -> 9
    | Ten | Jack | Queen | King-> 10
    | Ace -> 11

Our Active Patterns are going to look at hands and tell us something about them. Every hand has a Score so (|Score|) can be a Single Total Active Pattern. And, it’s really easy to write.

let (|Score|) (hand: Card List) =
    hand
    |> List.sumBy CardScore

The number of cards is also a Single Total Active Pattern, and a useful piece of information, as we’ll see in a moment.

let (|Cards|) (hand: Card List) =
    List.length hand

We now have everything we need to fit a hand of cards into one of five possibilities. A Multiple Active Pattern will work. Notice how the code is about as close to a description of the rules as you can get. We literally list the various types of hands. Blackjack is when we have 2 cards with a combined score of 21, A Pair is when we have two cards with the same Rank and we don’t care about the Suits.

let (|Bust|Blackjack|TwentyOne|Pair|Under|) (hand: Card List) =
    match hand with
    | Score s when s > 21 -> Bust
    | Cards 2 & Score 21 -> Blackjack
    | Score 21 -> TwentyOne
    | [(r1,_); (r2,_)] when r1 = r2 -> Pair r1
    | Score s -> Under s

Some of the cases simply identify the type of hand Bust, Blackjack, TwentyOne. Others package some information with the hand type. Pair tells us the Rank of the pair. Under tells us the score. This Multi-Case active pattern is working with Single Case Active Patterns, and together they make the following function really easy to write.

let DescribeHand (hand: Card List) = 
    match hand with
    | Bust -> "You're over 21, you're bust"
    | Blackjack -> "BLACKJACK!!! Yeah!!!"
    | TwentyOne -> "TwentyOne, you should probably stick"
    | Pair r -> sprintf "A pair of %As You can split" r
    | Score s -> sprintf "You have %d, want me to hit you?" s

And here’s where it gets really fun, if for any reason someone goes and adds a new value to the Active Pattern, a new type of hand, then our DescribeHand function will fail to compile. We would no longer be covering all of the possibilities.

You don’t get that kind of protection when you use partials and catch-alls.

Caveats
There are one or two things to note about Multi-Case active pattern.

  • They can have a maximum of 7 values. Our example above had only 5, but there are 10 named Poker Hands, so for Poker we’d need take a slightly different approach. Typically if you are looking at a lot of values putting them in separate Single Partial Active Patterns may make more sense, despite the concerns expressed above.
  • They can not be Partial. Multi-Case Patterns exist precisely to give the exhaustive pattern matching. If you are going to require catch all clauses then you might as well use Single Partial Patterns.
  • They can not have additional arguments beyond the one argument that they match on. You can define a multi case active pattern function with additional arguments but you will receive an error if you attempt to use it. That may seem odd, but as we’ll see in the next (and final) post, you can partially apply a Multi-Case pattern to create one that accepts one argument, and that can then be used.

We’ve now covered all of the different types of Active Patterns, we’ve also touched on a number of other areas within FSharp from Option Types to Currying, Tuples to Discriminated unions. If you’ve stayed with me then you should feel like you “get” active patterns, and you may have picked up some extra FSharp along the way.

Active Patterns are incredibly flexible, we haven’t even scratched the surface of all the way’s they can be used. That’s down to you.

There is one more post to go, it will cover some strange and wonderful things you can do with what you’ve learned. We’ll partially apply the Multi-Case patterns, and we’ll nest active patterns to match over complex hierarchical data structures.

Active Patterns: Single Partial With Params (|A|_|) x

We close out the discussion of Single Active Patterns by adding parameters to the partial active pattern. If you’ve read the post on adding parameters to the Single Total Active Pattern then there is absolutely nothing new here, it works in exactly the same way.

For that reason I’m not going to use this post to explain how to do it, I’m just going to work through an example and leave it at that.

In the last post I created some active patterns that we could use to evaluate a rudimentary arithmetic expression. There was a lot of duplicated code between the Addition and Subtraction cases.

Here’s a first stab at eliminating some of that by extracting the underlying behavior and using Partial Application. This has all been covered already in this post.

Parsing numbers is handled just like it was before, no change here.

let (|Number|_|) (str: string) =
    match Int32.TryParse(str) with
    | (true, n) -> Some(n)
    | false, _ -> None

Now instead of fully implementing Addition and Subtraction independently of each other, we have a more general purpose pattern called (|BinaryOp|_|). Note that the operator (the text to look for in the expression) is an argument to this function.

let (|BinaryOp|_|) operator (str: string) =
    let SplitAt (op: string) (str: string) =
        let pos = (str.IndexOf op)
        (str.Substring(0, pos),str.Substring(pos + 1, str.Length - pos - 1))

    if str.Contains(operator) then 
        Some (SplitAt operator str)
    else
        None

Now creating our Addition and Subtraction patterns is simple.

let (|Addition|_|) = (|BinaryOp|_|) "+"
let (|Subtraction|_|) = (|BinaryOp|_|) "-"

And the Match works just like it did before, no change here.

let rec Eval str =
    match str with
    | Number x -> x
    | Addition (l, r) -> Eval(l) + Eval(r)
    | Subtraction (l, r) -> Eval(l) - Eval(r)
    | _ -> raise (System.ArgumentException("Invalid Expression " + str))

That’s all fine, but notice how our match expression needs to know how to respond to the Addition and Subtraction cases, this isn’t ideal.

    | Addition (l, r) -> Eval(l) + Eval(r)
    | Subtraction (l, r) -> Eval(l) - Eval(r)

We could do the following.

type Operator = string * (int->int->int)

The type ‘Operator’ consists of a string (the token) and a function int->int->int (I’m keeping things simple here, int only). Now our underlying BinaryOp pattern just doesn’t take a string to search for, it also takes a function to perform when that string is found.

let (|BinaryOp|_|) (operator: Operator) (str: string) =
    let token, operatorFunction = operator
    let SplitAt (op: string) (str: string) =
        let pos = (str.IndexOf op)
        (operatorFunction, str.Substring(0, pos),str.Substring(pos + 1, str.Length - pos - 1))

    if str.Contains(token) then 
        Some (SplitAt token str)
    else
        None

We use destructuring assignment to extract the token and the function from operator. The token is used to split the string, but the function is simply passed back from the pattern so that the calling match expression can use it.

Defining the Addition and Subtraction patterns is now slightly different, we need to include both the token and the function.

let (|Addition|_|) = (|BinaryOp|_|) ("+", (+))
let (|Subtraction|_|) = (|BinaryOp|_|) ("-", (-))

As mentioned above our match expression needs to be modified to get the function back from the active pattern so that it can apply it to the left and right subexpressions. Now that both Addition and Subtraction are handled identically, we can combine them using an or ‘|’ pattern.

let rec Eval str =
    match str with
    | Number x -> x
    | Addition (f, l, r) | Subtraction (f, l, r)
    		-> f (Eval(l)) (Eval(r))
    | _ -> raise (System.ArgumentException("Invalid Expression " + str))

And that’s it for Single Case Active Pattern both the Total and Partial variety. We’ve covered a lot of ground. In the next post we’ll move on the Active Patterns that have Multiple results. If you’ve managed to stay with me this far nothing that remains will phase you.

Active Patterns: Single Partial (|A|_|)

I’ve referred to all of the Active Patterns we have seen so far in this series as ‘Single Total’. It’s time to look at the distinction between ‘Total’ and ‘Partial’ Active Patterns.

To understand Partial Active Patterns you need to have some understanding of Option Types’. If they are new to you, I’d encourage you to read up on them before continuing. A great place for reading about this, and F# generally is FSharpForFunAndProfit.

When we write a function to count the upper case characters in a string, there is always an answer, even if that answer is 0. Not all functions are so clear cut. If we write a function to parse a string into a number, it is possible to provide strings that simply can’t be parsed.

ParseNumber(“21”) // OK
ParseNumber(“Tango Foxtrot”) // What can we do with this?

All of the examples we’ve seen so far have involved Active Patterns that are just transformation functions. The match expression uses guards, literal values, variables and wildcards to decide how it will match on the returned value.

Partial Active Patterns take back some of that control. A ParseNumber active pattern can decide that it won’t match a value regardless of how the match expression is constructed. It does this by returning an Option Type. When it returns ‘Some Value’ the match expression will deal with that value just as before, but if the Active Expression returns ‘None’ then there is no match and the value falls through and must be handled by a different pattern.

Since we’ve been talking about parsing numbers, let’s look at an example.

let (|Number|_|) (str: string) =
    match Int32.TryParse(str) with
    | (true, n) -> Some(n)
    | false, _ -> None

The Active Pattern name now includes an extra component. The underscore (wildcard) indicates that this is a partial Active Pattern. Not every string that is passed to this pattern can be turned into a Number. We can use this in a match expression as follows.

let IsItANumber (str: string) =
    match str with
    | Number n -> sprintf "That was number %d" n
    | _ -> sprintf "Not a number"

Option Types are still valid types. You can return an option from a SingleTotal active pattern.

let (|Number|) (str: string) =
    match Int32.TryParse(str) with
    | (true, n) -> Some(n)
    | false, _ -> None

let IsItANumber (str: string) =
    match str with
    | Number (Some n) -> sprintf "That was number %d" n
    | _ -> sprintf "Not a number"

The remainder of the Active Pattern is identical, but, because we used the SingleTotal form of the Active Pattern we have to unpack the value n from the option type using the ‘Some’ keyword. By using the Partial Form of the active pattern we get that for free.

I’ll be honest I find that a little confusing because the signatures of both forms of the pattern are the same (string -> int option). Don’t worry too much about it (I don’t), if you are writing Single case Active Patterns that can’t match all possible inputs then use the Partial form.

The Infamous FizzBuzz
Let’s take another example of a Total Active Pattern and convert it to a Partial, and see what happens. Here is the infamous FizzBuzz

let (|Multiple|) m n =
    if n%m=0 then true
    else false

let (|Fizz|) = (|Multiple|) 3
let (|Buzz|) = (|Multiple|) 5

let FizzBuzz n =
    match n with
    | Fizz true & Buzz true -> "FizzBuzz"
    | Fizz true -> "Fizz"
    | Buzz true -> "Buzz"
    | _ -> n.ToString()

The Active Pattern (|Multiple|) returns a boolean indicating whether parameter ‘n’ is a multiple of ‘m’. Because it returns true or false, our match expression needs to specify those literals in order to catch the various cases.

Here’s the same code rewritten using Partials

let (|Multiple|_|) m n =
    if n%m=0 then Some Multiple
    else None

let (|Fizz|_|) = (|Multiple|_|) 3
let (|Buzz|_|) = (|Multiple|_|) 5

let FizzBuzz n =
    match n with
    | Fizz & Buzz -> "FizzBuzz"
    | Fizz -> "Fizz"
    | Buzz -> "Buzz"
    | _ -> n.ToString()

The booleans are gone, the Active Patterns now return Multiple, Fizz, Buzz and None leading to a cleaner match expression. Both those examples also use Currying and the ‘&’ pattern from the last post.

An Expression Evaluator
Let’s finish this post with one last example, a little more ambitious this time. We’ll start with a match expression and see if we can figure out the Active Patterns to make the magic happen.

let rec Eval str =
    match str with
    | Number x -> x
    | Addition (l, r) -> Eval(l) + Eval(r)
    | Subtraction (l, r) -> Eval(l) - Eval(r)
    | _ -> raise (System.ArgumentException("Invalid Expression " + str))

This function evaluates expressions. It seems to only handle Numbers, Addition and Subtraction so we’ll need Active Patterns for each of those.

It looks like the expression is represented as a string, but the pattern matching would be basically identical even if expression were represented in another way. That’s one of the perks at coding at a higher level of abstraction.

Number looks like the example we’ve already seen, let’s do that first.

let (|Number|_|) (str: string) =
    match Int32.TryParse(str) with
    | (true, n) -> Some(n)
    | false, _ -> None

Incidentally if that syntax for the TryParse function is throwing you a little, have a look at this post.

Both Addition and Subtraction accept strings and return what look like tuples representing the left and right subexpressions.

let (|Addition|_|) (str: string) =
    let SplitAt (op: string) (str: string) =
        let pos = (str.IndexOf op)
        (str.Substring(0, pos),str.Substring(pos + 1, str.Length - pos - 1))

    if str.Contains("+") then 
        Some (SplitAt "+" str)
    else
        None

let (|Subtraction|_|) (str: string) =
    let SplitAt (op: string) (str: string) =
        let pos = (str.IndexOf op)
        (str.Substring(0, pos),str.Substring(pos + 1, str.Length - pos - 1))

    if str.Contains("-") then 
        Some (SplitAt "-" str)
    else
        None

Some code duplication there, but it will work. Both patterns check the incoming string. If it contains the right operator the patterns split the string and returns either side as the elements of a tuple. The Eval function then takes those two subexpressions, recursively evaluates them and applies the right operator to bring the two expressions back together.

The next post will be very short and will show how to use parameters with Partial Active Patterns. This won’t need much explaining because it’s the same process as adding parameters to Total Active Patterns which you’ve already seen. We’ll use parameters to rewrite this expression evaluator and get rid of the duplicated code.