Monday, December 29, 2008

The F# library provides a variety of functions (based on the printf functions found in OCaml) that produce formatted text.

printf outputs formatted text to the console using the stdout stream.
printfn outputs formatted text suffixed with a new-line character to the console using the stdout stream.
eprintf outputs formatted text to the console using the stderr stream.
eprintfn outputs formatted text suffixed with a new-line character to the console using the stderr stream.
sprintf returns formatted text as a string.
bprintf appends formatted text to a System.Text.StringBuilder.
fprintf writes formatted text to a System.IO.TextWriter.
fprintfn writes formatted text suffixed with a new-line character to a System.IO.TextWriter.
twprintf writes formatted text to a System.IO.TextWriter.
twprintfn writes formatted text suffixed with a new-line character to a System.IO.TextWriter.

The functions above are especially powerful because the F# compiler will type-check the format arguments and give design-time errors.

Type-safe Format String Error with Tooltip

While this set of functions covers most of the cases where formatted text is needed, there is one glaring omission: debug output. If we want to pass formatted text to System.Diagnostics.Debug.Write, we have to do it using sprintf like so:

System.Diagnostics.Debug.Write(sprintf "The answer = %d" 42)

Obviously, that's not ideal. What we would really like is a function that behaves exactly like the other printf functions but writes debug output. Fortunately, extensibility has been built into the F# library, making it possible to create additional formatting functions that benefit from the same sweet type-checking. So, how do we go about doing that? The trick is to wrap our functions around a special F# library function, ksprintf.

ksprintf is similar to sprintf in that it formats text as a string. However, instead of returning that string to the caller, it passes the string into a continuation.

I haven't covered the broad topic of continuations yet because a) they can be pretty eye-crossing when presented plainly, and b) there are already fantastic treatments out there. The basic idea is to pass a lambda1 (the so-called continuation) into a computation that will be executed when the computation is finished. Really. That's it. This is a simple idea, but it can become complicated quickly. However, in the case of ksprintf it remains simple. We'll pass a lambda that calls Debug.Write with the final string after it has been formatted.

module Debug =
  open System.Diagnostics

  let writef fmt = Printf.ksprintf (fun s -> Debug.Write(s)) fmt

  let writefn fmt = Printf.ksprintf (fun s -> Debug.WriteLine(s)) fmt

In fact, the wrapper lambdas are redundant because Debug.Write and Debug.WriteLine have overloads that match the expected signature. We can simply pass the functions themselves and remove the wrappers:

module Debug =
  open System.Diagnostics

  let writef fmt = Printf.ksprintf Debug.Write fmt

  let writefn fmt = Printf.ksprintf Debug.WriteLine fmt

Just drop that code into an F# project, and you'll be writing debug output in a beautiful, concise F# style.

Debug.writef "The answer = %d" 42

You'll even get helpful design-time type errors:

Debug.writef Type-safe Format String Error with Tooltip

Now it's just a matter of convincing the F# team to add it to the libraries. ;-)

1Did It With .NET readers probably already know that "lambda" = "anonymous function".

posted on Monday, December 29, 2008 11:35:14 AM (Pacific Standard Time, UTC-08:00)  #    Comments [2]

kick it on DotNetKicks.com
 Wednesday, December 17, 2008

It’s that time of year again. CodeMash time.

When I first moved to the Seattle area, I was concerned that I wouldn’t be able to come back to Ohio for this year’s CodeMash. Of all of the conferences that I’ve attended over the years, CodeMash has been among the most rewarding, and I really didn’t want to miss this one. Fortunately, the stars have aligned, and my family’s holiday vacation is bringing me back to the Midwest just in time to join in on all the fun.

This year’s speaker list is just insane. With names like Bill Wagner, Richard Campbell, Steve Smith, Mads Torgersen and David Laribee, I’m expecting to have a very full and satisfied brain. But CodeMash is about more than just the sessions; it’s also about the pure geek nirvana of hanging out with a group of people who are just as excited about technology as I am.

Given the list of heavyweights speaking this year, I feel pretty honored to be filling one of the slots. If you’re coming to CodeMash, check out my talk, “Multi-threading Mojo with F#.” It should be a blast.

CodeMashGears

posted on Wednesday, December 17, 2008 11:39:46 PM (Pacific Standard Time, UTC-08:00)  #    Comments [6]

kick it on DotNetKicks.com