Friday, April 04, 2008

Isn't She Hot? 

I have a terrible, secret shame: my writing skills are lousy.

For me, perhaps the most difficult aspect of blogging is the writing process. Sometimes I feel inspired, but more often, I struggle. No matter how profound my level of inspiration is, bugs always seem to work themselves into my writing. Missing words, grammar slip-ups, poor phrasing—you name it. I feel as if I've been cursed.

My frustration is probably due to my dislike of writing in school. Back then, it simply didn't interest me. I was too busy learning to code against the Zilog Z80, and playing Trade Wars on my local BBS. I suppose it didn't help that, for many years, the vast majority of my reading consisted of either technical books or comic books.

When I began blogging in August of 2006, my writing was... unpolished. I composed my posts with the same grace that elephants construct model airplanes. Sadly, I couldn't recognize my own weakness.

For awhile, my blog stayed pretty low on the radar. I wrote a few technical articles, but in February of 2007, I really hit my (first) stride writing articles about functional programming concepts using C# 2.0. I rolled into March, picking up steam until my writing and I reached an impasse.

On March 23, 2007, I posted an article that earned me a few negative emails. None of the emails criticized my content (which is still pretty cool). Instead, they (gently) pointed out typos, poorly-constructed sentences, and unclear tidbits.

Feeling frustrated and inept, I asked my trophy wife—who graduated with a minor in English Education—to take a look at my article. Graciously, she corrected my grammar, and I promptly re-posted it. So, everything was OK now, right? Wrong. The wind in my blogging sails had died down. My dear trophy wife continued to help me with blog posts, but my desire to blog had waned. Eventually, my output shrank to just a trickle.

Finally, on August 1, 2007, I was bit by the blogging bug for a second time. But this time was different. This time, I was playing it smart. I "employed" my trophy wife as a full-time editor. Since then, she has poured over every blog post with me.

My trophy wife is an especially good editor. In addition to navigating through my grammatical mine fields, she works hard to actually understand the concepts that I'm trying communicate. The process results in better-written articles that are more easily understood.

Since I got my second wind, blogging has been a joy. It's much more fun to have someone to bounce ideas off of ([ed.] Never end a sentence with a preposition, silly). But most importantly, it's provided a way to bring my trophy wife into my world.

posted on Friday, April 04, 2008 11:55:18 AM (Pacific Standard Time, UTC-08:00)  #    Comments [6]

kick it on DotNetKicks.com
 Thursday, April 03, 2008

 WeigtingApplesAndOranges

This recent blog post caused quite a stir on the F# mailing list. The post presents two solutions for Project Euler Problem 14: one in C# and the other in F#. The C# version clearly is hand-optimized for speed (and is indeed very fast), but the F# solution isn't. Instead, the F# code appears to be written with elegance and brevity in mind. Robert Pickering presented a challenge to create a faster F# solution, and the F# mailing list (which had been dormant for a couple of weeks) literally exploded with ideas.

Before we go too far afield, below are the instructions for Project Euler Problem 14.

The following iterative sequence is defined for the set of positive integers:

nn/2 (n is even)
n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.

As you can see, the problem boils down to generating one million sequences and counting the number of terms in each to find the longest. It's not rocket science, but there are many ways to optimize the solution. However, I'm not interested in creating the most optimal F# code to compete with the C# version. That's already been done by many of the gurus. Instead, I'd like to know if we can write C# code that more closely matches the algorithm used by the F# solution. Let's see how C# matches up when playing F#'s game.

Below is the F# solution that's caused so much debate.

#light

let seqLength n =
  n |> Seq.unfold
    (fun x -> match x with
             
| x when x = 0L      -> None
              | x when x = 1L      -> Some(1L, 0L)
              | x when x % 2L = 0L -> Some(x, x / 2L)
              | _                  -> Some(x, 3L*x + 1L))
    |> Seq.length

[for i in 1L..1000000L -> (i, seqLength i)]
  |> List.fold1_left(fun (ai,al) (i,l) -> if l > al then (i,l) else (ai,al))
  |> (fun (x,y) -> x ) |> print_any

If you've been following my F# articles, the code above shouldn't contain anything new. Pattern matching, tuples, option types, list comprehensions, functions and the forward pipe operator should all be reasonably familiar. The only item that truly requires explanation is the Seq.unfold function.

In F#, seq<'a> is an alias for the .NET interface, IEnumerable<T>, which is implemented by every collection in the Base Class Library and is the centerpiece of LINQ to Objects. In fact, in the F# libraries, seq<'a> is defined very simply as...

type seq<'a> = IEnumerable<'a>

See? Simple.

Seq.unfold is a library function that creates a seq<'a>, given a generator function. The resulting seq<'a> is lazily evaluated. That is, when a value in the seq<'a> is requested, the generator function is called to calculate it. In practice, it's similar to a C# iterator. The signature of Seq.unfold looks like so:

val unfold : generator: ('b -> ('a * 'b) option) -> 'b -> seq<'a>

The generator function is usually the part that trips people up. When called, the generator is passed a bit of state. This state is initialized by the second argument passed to Seq.unfold. To confuse matters further, the generator returns an option type containing a tuple. This option+tuple result represents three pieces of information:

  1. The option type indicates whether or not the sequence should continue. I.e., returning None signals the end of the sequence.
  2. The first part of the tuple is the current item in the sequence.
  3. The second part of the tuple is the bit of state that will be passed to the generator the next time it's called.

Note that the state and the result aren't required to be of the same type. This means that you can use Seq.unfold to generate some fairly flexible sequences. For example, we could produce the counting numbers as a sequence of strings.

1 |> Seq.unfold (fun i -> Some(i.ToString("#,#"), i + 1))

The above code produces an infinite sequence. That's OK because the sequence is lazy. However, we could introduce starting and stopping values by declaring a function and modifying the generator.

let count (start : int) stop =
  start |> Seq.unfold (fun i -> if i > stop then None
                                else Some(i.ToString("#,#"), i + 1))

That function can be called like so (using the F# Interactive Environment):

> count 1000 1003;;

val it : seq = seq ["1,000"; "1,001"; "1,002"; "1,003"]

Now that we have a better understanding of how Seq.unfold works, consider the generator function from the F# solution shown earlier.

(fun x -> match x with
          | x when x = 0L      -> None
          | x when x = 1L      -> Some(1L, 0L)
          | x when x % 2L = 0L -> Some(x, x / 2L)
          | _                  -> Some(x, 3L*x + 1L))

This very elegantly represents the rules of the sequence as defined by Project Euler.

nn/2 (n is even)
n → 3n + 1 (n is odd)

To create a C# solution that maps to the F# solution, we'll need to define an Unfold function. To do that, we need to create Options and Tuples. Below are the interfaces of the Option and Tuple types we'll use in C#.

public sealed class Option<T>
{
  public bool IsNone { get; }
  public bool IsSome { get; }
  public T Value { get; }

  public static Option<T> None { get; }
  public static Option<T> Some(T value) { }
}

public static class Option
{
  public static Option<T> Some<T>(T value) { }
}

public sealed class Tuple<T1, T2>
{
  public T1 Fst { get; }
  public T2 Snd { get; }
}

public static class Tuple
{
  public static Tuple<T1, T2> New<T1, T2>(T1 fst, T2 snd) { }
}

I don't want to derail our discussion by delving too deeply into them. If you're interested, you can download the source and explore them at your leisure. For our purposes, you can trust that they work as expected. One point of interest is the additional Option.Some<T>() and Tuple.New<T1, T2>() helper methods. These are in place to allow us to remove some code-clutter by taking advantage of the C# compiler's type inference for generic type parameters.

Defining Unfold as a C# iterator is fairly straightforward—that is, once you get past the scary nested generic type of the generator parameter.

public static IEnumerable<TResult> Unfold<T, TResult>(
  Func<T, Option<Tuple<TResult, T>>> generator, T start)
{
  var next = start;

  while (true)
  {
    var res = generator(next);
    if (res.IsNone)
      yield break;

    yield return res.Value.Fst;

    next = res.Value.Snd;
  }
}

Using Unfold, we can write C# code that determines the length of one of the Project Euler sequences, given a starting value.

public static long SeqLength(long start)
{
  return Unfold(x =>
    {
      if (x == 0L)
        return Option<Tuple<long, long>>.None;
      else if (x == 1L)
        return Option.Some(Tuple.New(1L, 0L));
      else if ((x % 2L) == 0L)
        return Option.Some(Tuple.New(x, x / 2L));
      else
        return Option.Some(Tuple.New(x, (3L * x) + 1L));
    }, start).Count();
}

That code is remarkably similar to the original F# code (restated below).

let seqLength n =
  n |> Seq.unfold
    (fun x -> match x with
             
| x when x = 0L      -> None
              | x when x = 1L      -> Some(1L, 0L)
              | x when x % 2L = 0L -> Some(x, x / 2L)
              | _                  -> Some(x, 3L*x + 1L))
    |> Seq.length

OK. The bulk of the work is complete. The rest of the solution can be coded with a query expression.

public static long GetLongestSequence()
{
  return (from i in Enumerable.Range(1, 1000000)
          select new { Start = i, Length = SeqLength(i) })
          .Aggregate((x, y) => y.Length > x.Length ? y : x)
          .Start;
}

Again, the symmetry between the C# query expression above and the original F# code below is striking.

[for i in 1L..1000000L -> (i, seqLength i)]
  |> List.fold1_left(fun (ai,al) (i,l) -> if l > al then (i,l) else (ai,al))
  |> (fun (x,y) -> x ) |> print_any

Where do we stand in terms of performance? Well, the C# code that we just wrote takes about 16 seconds to find the correct answer on my machine, but the F# solution comes in at around 12 seconds. The C# solution from the original blog post executes in about .047 seconds on my machine, but Robert Pickering's final F# solution takes .064 seconds. Is there a clear winner? In my opinion, no, not really.

So, what have we learned? When one takes the time to implement the same algorithm in each language, F# and C# really have a similar performance profile. However, the F# compiler definitely is tuned for elegance and beauty.

Instead of comparing apples to oranges, try comparing apples to apples and oranges to oranges. A performance comparison between two algorithms written in two different languages is interesting on some level, but it isn't really a fair comparison.

Download the source code for this article

posted on Thursday, April 03, 2008 4:40:31 AM (Pacific Standard Time, UTC-08:00)  #    Comments [3]

kick it on DotNetKicks.com
 Tuesday, April 01, 2008

Today is April Fool's Day—the day when many of us celebrate just how gullible we really are. Celebrants enjoy the day by spoofing co-workers and engaging in fun hoaxes and practical jokes.

Over the years, I've personally been the target of many an April Fool's prank. Considering today's date, I'm not sure what to make of the following email that I received this morning. Am I the target of yet another joke?

Congratulations! We are pleased to present you with the 2008 Microsoft® MVP Award! The MVP Award is our way to say thank you for promoting the spirit of community and improving people’s lives and the industry’s success every day. We appreciate your extraordinary efforts in Visual C# technical communities during the past year.

I suppose it's possible that Microsoft has a thoroughly sick sense of humor, and this is just an elaborate hoax. On the other hand, it could be that Microsoft has absolutely no sense of humor and doesn't realize that today isn't the most optimal day to be sending out congratulatory emails.

I feel that I have to give this email two responses:

  1. If this is real, I am completely humbled to be a recipient of the MVP Award this year. Blogging, speaking and educating are activities that I find very rewarding, and it's flattering to be recognized for them.
  2. If this is just an elaborate joke, I'm thoroughly disgusted and saddened by the juvenile attempt at humor. People have feelings, ya' know!

How hard is it to send these emails on March 31st or April 2nd? :-) That would clear up a lot of confusion.

P.S. I know it's real. Thanks Microsoft! I am truly honored. No joke.

posted on Tuesday, April 01, 2008 7:44:09 AM (Pacific Standard Time, UTC-08:00)  #    Comments [10]

kick it on DotNetKicks.com
 Thursday, March 27, 2008

Recently, I googled my first name. The search yielded some startling results. Not only was I surprised to find my modest blog on the front page, but... well... see for yourselves.

GoogleDustin

Sadly, soon after came the inevitable smack down.

GoogleDustin2

It's on. Now that I've had a taste of power, I'm willing to go to great lengths to quench my thirst. Look out Hoffman! I don't care if you are my namesake...

You're next Screech. No bell will save you this time.

posted on Thursday, March 27, 2008 4:15:52 PM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
 Monday, March 24, 2008

Last month, I was scheduled to speak at the Findlay Area .NET Users Group (FANUG), but the meeting was canceled due to weather. This month, my good friends Jason Follas and Greg Huber were scheduled to speak, but a last-minute conflict has thrown a monkey wrench into the works. After passing a few emails back and forth, Jason and Greg have decided to reschedule. Instead, I'll be giving my Functional C# talk in Findlay tomorrow night. I hope to see you there!

Title: Functional C#

Abstract: In recent years, many features have been added to the C# language that make it possible to write programs using techniques from other programming paradigms. Chief among these is functional programming. Often regarded as only being academically useful, functional programming has many practical uses, some of which appear within the .NET Framework itself. In this session, we'll examine some ideas taken from functional programming and see how they might be implemented using language features that already exist within C#. In addition, we'll highlight ways in which the .NET Framework APIs borrow from functional programming.

posted on Monday, March 24, 2008 8:11:54 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com
 Thursday, March 20, 2008

GoogleAds

posted on Thursday, March 20, 2008 12:00:23 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com

A few days ago, my friend Michael Letterle (the artist formerly known as Michael.NET) twat the following tweet:

MichalL-20YearsToLate

The story Michael referred to is Landon Dyer's "Donkey Kong and Me" blog post, which chronicles his conversion of the Donkey Kong arcade game to the 8-bit Atari 400/800 systems. (Screenshots and a review of the port can be found here.) A fascinating yarn, Dyer's post evokes a feeling of nostalgia for the swashbuckling coder days of more than two decades ago. His recent post about the development of the Atari ST is equally enjoyable.

I've often shared Michael's sentiment. Sometimes, I feel like I was born a bit too late. At the advanced age of 0x20, I am fascinated by stories of the Herculean coding efforts of those who came before me—the original early adopters. (Although, there's a strong argument that the present day is just as, if not more, exciting.) Perhaps the most interesting aspect of tech history is how our forefathers were forced to invent creative solutions for just about everything. For me personally, that's what makes "Donkey Kong and Me" so much fun. The same appeal can be found in the early-Macintosh hardware-tweaking stories at Andy Hertzfeld's Folklore.org.

To fuel my interest in computer tech history, I've recently begun re-reading its bible: Programmers At Work.

ProgrammersAtWork2

Published in 1986, this book features interviews with an amazing array of programmers, including figures like Gary Kildall, Charles Simonyi, Jaron Lanier and even Bill Gates. It's out-of-print but can still be purchased used. (I "borrowed" my water-damaged copy from my father's bookshelf). Thankfully, Susan Lammers, the author, has recently started a "Programmers At Work" blog where she's posting the original interviews. So, if you can't find the book, these classic interviews should all be available soon.

What interesting tech history articles or books have you read recently?

posted on Thursday, March 20, 2008 9:39:47 AM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Wednesday, March 19, 2008

Yesterday, I attended the Microsoft Detroit Launch Event and the Geek Dinner that immediately followed. (Important thanks go to Microsoft for graciously picking up our food tab at the Geek Dinner.)

What a blast! It was exciting to visit with old friends and meet new people. Here are a few shout-outs:

  • James Bender: Night elves are totally lame. You need to re-roll on WoW dude. Really, I'm kidding. Let's get together on Dalaran sometime.
  • Amanda DaPanda: I feel so bad that I wasn't following you on Twitter. The issue has been corrected. Let's talk some more about F#. Do you have a blog?
  • Michael Eaton: Someday you'll make it to a Metallica show.
  • Keith Elder: Awesome Geek Dinner! Thanks for setting this up. Also, thank you for suggesting that I use Windows Live Writer. I am a changed man.
  • Jason Follas: Thanks for driving, hanging out and being such an all-around amazing guy.
  • Steven Harman: Your T-shirt was fantastic, and our discussion about Ruby was illuminating.
  • Nate Hoellein: It was good talking F# with you again.
  • Jim Holmes: Still nursing the wounds of your defeat at DevConnections, eh? :-) As always, it was a joy to see you.
  • Josh Holmes: Your advice was a blessing. It was wonderful to slow down and spend a little time together.
  • Ryan and Joel Lanciaux: It was cool finally meeting you guys in person. It's amazing that our lives have so many connections.
  • Michael Letterle (the artist formerly known as Michael.NET): I really do like your new handle and blog theme.
  • Jeff McWherter: Sorry for my huge faux paux! I'll make it up to you.
  • David Redding: It was a horrible feeling to realize that you are actually five years younger than me.
  • Chris Woodruff: Where the heck were you? You were missed.
  • Jay Wren: I keep forgetting that you're easily the funniest person I know.
posted on Wednesday, March 19, 2008 1:43:47 PM (Pacific Standard Time, UTC-08:00)  #    Comments [0]

kick it on DotNetKicks.com
 Friday, March 14, 2008

Recently, I was refactoring some trivial F# code, and the results were so elegant that I felt it would be instructive to share them. My tale begins simply with a list of lists...

> let lists = [[1;2];[5;6;7];[9;10];[3;4];[8]];;

val lists : int list list

Now, suppose we wanted to sort lists by the lengths of the inner lists. How might we do that? Easy! The F# libraries include a List.sort function which does the trick.

val sort: ('a -> 'a -> int) -> 'a list -> 'a list

List.sort takes two arguments. The first argument is a function used to compare elements from the list, and the second argument is the list to be sorted. Obviously, most of the work is in defining the first argument. This comparison function returns a negative value if the first element is less than the second, a positive value if the second element is less than the first, or zero if the two elements are, in fact, equal. With that in mind, we could sort lists using List.sort and List.length like so:

> List.sort (fun x y -> if (List.length x) < (List.length y) then -1
-                       elif (List.length x) > (List.length y) then 1
-                       else 0) lists;;

val it : int list list = [[8]; [1; 2]; [9; 10]; [3; 4]; [5; 6; 7]]

OK. It worked, but that's an awful lot of code. Typing all of that into the F# Interactive Environment is fraught with peril ([ed.] the author spelled "length" as "lentgh" at least twice).

Thankfully, F# provides a function, compare, which can be used to calculate a generic comparison of two arguments.

val inline compare: 'a -> 'a -> int

compare can do most of the heavy lifting and greatly decreases the amount of code we have to write.

> List.sort (fun x y -> compare (List.length x) (List.length y)) lists;;

val it : int list list = [[8]; [1; 2]; [9; 10]; [3; 4]; [5; 6; 7]]

That's much better!

NeRd Note
Did you know that the .NET Framework also provides an API for generic comparison? For types that implement IComparable or IComparable<T>, System.Collections.Generic.Comparer<T>.Compare() can handle the dirty work!
int CompareGuids(Guid x, Guid y)
{
  return Comparer<Guid>.Default.Compare(x, y);
}

Our sort is looking pretty good, but we can do better. Let's take a closer look at the comparison function we're passing to List.sort.

(fun x y -> compare (List.length x) (List.length y))

What exactly are we doing here? Essentially, we're inserting a function application for each argument before calling compare. It sure would be nice to have a function that generalizes this for us. Perhaps something like this:

let inline compareWith f x y = compare (f x) (f y)

I can already sense the snickers. Some of you are thinking, "How could that possibly work? There aren't any types! How would F#'s statically-typed compiler handle that?"

The answer to my hecklers is yet another reason why I love F#: automatic generalization. If necessary, F# will attempt to insert generic type parameters into a function as part of its type inference. This allows very sophisticated code to be written with breathtaking succinctness. The following code shows automatic generalization in action.

> let inline compareWith f x y = compare (f x) (f y);;

val inline compareWith : ('a -> 'b) -> 'a -> 'a -> int

As you can see, F# allows us to define the essence of a function without the noise of type annotations. It looks very similar to code written in dynamically-typed languages, but has all of the benefits of static-typing.

Armed with our new compareWith function (any chance of getting that into the libraries Don?), we can sort lists using List.length like so:

> List.sort (fun x y -> compareWith List.length x y) lists;;

val it : int list list = [[8]; [1; 2]; [9; 10]; [3; 4]; [5; 6; 7]]

But wait! There's more!

I intentionally inserted what I consider to be a sophomoric blunder in that last bit of code. Try to find it. Notice that both of the parameters of our anonymous comparison function are passed, in order, as the last two arguments of compareWith. That's a big clue. Here's another. Consider the signatures of List.sort and comparewith. I'll highlight the interesting bits.

val sort: ('a -> 'a -> int) -> 'a list -> 'a list

val inline compareWith : ('a -> 'b) -> 'a -> 'a -> int

Do you see it? compareWith returns a function whose signature matches the signature of the comparison function expected by List.sort. In essence, the anonymous function is an extra "function layer" that really isn't necessary. Instead, we could write this1:

> List.sort (compareWith List.length) lists;;

val it : int list list = [[8]; [1; 2]; [9; 10]; [3; 4]; [5; 6; 7]]

This an excellent example of the benefits of currying and partial application (and yet another reason why I love F#). If you need to brush up, I've written about these topics in the past here, here and here.

There is one final bit of refactoring that I'd like to do. Notice how lists appears at the very end of the argument list for List.sort. We can make the code more readable by moving lists ahead of List.sort and using the forward pipe operator (|>) like so:

> lists |> List.sort (compareWith List.length);;

val it : int list list = [[8]; [1; 2]; [9; 10]; [3; 4]; [5; 6; 7]]

Now the code reads like an English sentence:

"Take lists and sort it, comparing with List.length."

It's a tiny jump to see that other functions could be easily used to sort lists. For example, we might sort using the head of each inner list (assuming that none of the inner lists is the empty list).

> lists |> List.sort (compareWith List.hd);;

val it : int list list = [[1; 2]; [3; 4]; [5; 6; 7]; [8]; [9; 10]]

Or, we could sort lists by the sum of each inner list (using List.fold_left with the + operator to perform the sum).

> lists |> List.sort (compareWith (List.fold_left (+) 0));;

val it : int list list = [[1; 2]; [3; 4]; [8]; [5; 6; 7]; [9; 10]]

The possibilities are endless!

Next time, we'll take a closer look at the wickedly clever forward pipe operator to see how its very existence hangs upon currying.

1If you don't immediately see why this works, try again. Work it out on paper. The reward is worth the effort.

posted on Friday, March 14, 2008 10:18:34 AM (Pacific Standard Time, UTC-08:00)  #    Comments [1]

kick it on DotNetKicks.com