The following C# code is typical of how we might create an array containing
the natural numbers from 1 to 20:
There's nothing special about that code. It's representative of the sort of
thing that we write all the time. However, it won't fly in the functional
world because it's written in an
imperative style. That is,
the code specifies the exact steps that should be taken to create and
initialize the array:
In contrast, the F# libraries provide a special module, Array, for
manipulating single-dimensional .NET arrays in a more
and Array3 are also available for manipulating two- and three-dimensional arrays
respectively.) Using the Array module, the C# code above could be translated to
F# like so:
Instead of a specific code recipe, this F# code says (in a more
declarative fashion), "create an array of 20 elements, and use this function to
initialize each element." An interesting feature of the F# version is that the
type of the array is never declared. Because the compiler can infer that the result
of the passed function (fun x -> x + 1) will be an int, "a" must be an int array.
To me, this code is beautiful. In addition, it is declarative instead of
imperative; it describes what should be done but doesn't dictate
exactly how it should be done. When I see such elegant code, I
immediately start trying to figure out which of its aspects could be used to improve the
code in my daily C# work. Here's how we might "borrow" the F# "Array.init" function in C#:
With this function defined, we can rewrite our array creation sample
declaratively using C# 3.0 syntax.
Notice that this code takes advantage of the C# compiler's
type inference in the same
way that the F# sample does. Sweet!
Let's take a look at another example. Suppose we want to iterate through
all of the elements in our int array and output each element's value to the console. We have a
few of options available to us. First, there's the familiar for-loop approach:
Second, there's the more declarative foreach-loop:
Finally, the underused "Array.ForEach" BCL method
is also a possibility:
In addition, because "Console.WriteLine" has an overload which
accepts a single int parameter, we can rewrite the previous code without a lambda expression:
Now, for the monkey wrench. Suppose we want to print the index of each element in the array along
with the value. With this added requirement, the for-loop is our most attractive
because the indexer variable is already built in. The other two options would require
awkwardly creating an indexer variable and explicitly incrementing it. This
looks especially ugly with the "Array.ForEach" option.
How might we handle this in F#? Simple. F# provides an API designed to
iterate an array with an index.
Like the BCL's "Array.ForEach" method, F#'s "Array.iteri" iterates
through an array and applies the given function
to each element. The difference is that the
function to be applied includes an additional parameter representing the
element's index in the array.
Using F#'s "Array.iteri" as a model, we can define an equivalent function in
Now we can iterate our array and output the index and value of each element
to the console with one line of code!
Since we're using C# 3.0, we can declare "ArrayEx.Iterate"
as an extension method to make the client code more
In conclusion, using F# as a source of inspiration, it's easy to create APIs
that enable more declarative C# code to be written. Do you have a cool
declarative API that you've written for C# or VB? If so, I'd love to hear about
it. Feel free to post your creations in the comments or email me directly.
Page rendered at Saturday, May 18, 2013 1:47:43 AM (Pacific Standard Time, UTC-08:00)
If feel a bit behind and need to catch up on WPF, this is the book.
Great book on F# containing from Beginner to Advanced. It even has chapters on more arcane features of the language, such as Computation Expressions and Quotations.
Because this book provides source code in Standard ML, it's a fantastic
resource for learning F#. One bit of warning: this book does not teach classic
data structures. While structures such as binomial heaps and red-black trees
are presented, it is assumed that the reader already knows and understands
The opinions expressed herein are my own personal opinions and do not represent
my employer's view in any way.