0
comment
on 12/2/2009 10:23 AM

Composite Formatting is a feature of .NET framework that comes handy even for F# programmers. Yes, Printf-style formatting generally is much nicer with F#, but there are situations where the format string is not available statically. It can, for instance, be coming from a configuration file.

One common issue with Composite Formatting is that it is not immediately obvious how to expand named arguments. Fortunately, all the pieces of the puzzle are there.

Just a little bit of F#:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

    module Format =
open System
open System.Collections.Generic

let private Split (s: string) =
match s.IndexOf '|' with
| -1 -> (s, "")
| n  -> (s.Substring(0, n), s.Substring(n + 1))

type Table<'T>(dict: IDictionary<string, 'T>) =
new (pairs: seq<string * 'T>) =
new Table<'T>(Map.ofSeq pairs)

interface IFormattable with
member this.ToString(format, _) =
let (key, def) = Split format
if dict.ContainsKey key then
dict.[key].ToString()
else
def

Now we can use string keys (and default values) to expand on keywords within the format strings. This is handy:

1
2
3
4

    let fmt = "{0:schema|http}://{0:domain}{0:path}"
System.String.Format(fmt, Format.Table ["domain", "example.com"])
System.String.Format(fmt, Format.Table ["domain", "example.com"; "path", "/products"])
System.String.Format(fmt, Format.Table ["schema", "https"; "domain", "example.com"])

You can also pass Dictionary and Map objects to the Format.Table constructor.

Even better, Composite Formatting is available not only in String.Format but also in other places such as TextWriters.

As a functional programmer working with F#, I keep discovering basic .NET framework features. Even though this use of Composite Formatting must be trivial, I hope some of you will find it useful.