Mathias Brandewinder on .NET, F#, VSTO and Excel development, and quantitative analysis / machine learning.
23. September 2011 12:47

I had the pleasure to present at the North Bay .NET user group this week on F#, where people asked me all sorts of great questions. At some point, we got into List comprehensions – a convenient syntax to generate lists - via an example along these lines (which returns a list of the multiple of 2, from 2 to 40):

let list =
[ for i in 1 .. 20 do yield 2 * i ]

While slightly more complex, the actual example is in essence equivalent. A question followed: how complex can the code within the brackets be?

Well, pretty much as complex as you want it to be. Take this for instance:

let list =
[
for i in 1 .. 10 do yield 2 * i
for i in 1 .. 10 do yield 3 * i
]

This will return a list of the multiples of 2 from 2 to 20, followed in the same list by the multiples of 3 from 3 to 30. Nice.

But you can go much wilder, and start putting code in there, too. For instance, we can expand the previous example a bit and morph it into a nice and concise FizzBuzz:

type Fizzbuzz = Fizz | Buzz | FizzBuzz | Number of int

let fizzBuzz n =
[
let fizzBuzzConvert number =
if number % 2 = 0 && number % 5 = 0 then FizzBuzz
elif number % 5 = 0 then Buzz
elif number % 2 = 0 then Fizz
else Number(number)

for i in 1 .. n do yield fizzBuzzConvert i
]

We declare a discriminated union, covering all the possible outcomes of FizzBuzz, declare inside the comprehension itself a function that maps an integer to a FizzBuzz result, and generate the list of results from i to n. Running this in the interactive window results in the following:

let fizzBuzz n =
[
let fizzBuzzConvert number =
if number % 2 = 0 && number % 5 = 0 then FizzBuzz
elif number % 5 = 0 then Buzz
elif number % 2 = 0 then Fizz
else Number(number)

for i in 1 .. n do yield fizzBuzzConvert i
];;

type Fizzbuzz =
| Fizz
| Buzz
| FizzBuzz
| Number of int
val fizzBuzz : int -> Fizzbuzz list

> let f = fizzBuzz 20;;

val f : Fizzbuzz list =
[Number 1; Fizz; Number 3; Fizz; Buzz; Fizz; Number 7; Fizz; Number 9;
FizzBuzz; Number 11; Fizz; Number 13; Fizz; Buzz; Fizz; Number 17; Fizz;
Number 19; FizzBuzz]

I would classify List comprehension under the “nice to have” features – it’s perfectly possible to write excellent code without it. At the same time, it’s a very, very convenient way to work with Lists, which I now miss in C#…

4. August 2011 15:53

A fun problem came my way today. Imagine that you are the owner of a renowned brewery in Bizzarostan, a country where beer is sold only in 7-packs and 13-packs, sometimes described as the ++ packs. Beer is a serious matter in Bizzarostan, and buying single bottles is not tolerated by the law.

You take great pride in doing what’s best for your customers, so when a customers asks you for, say, 20 beers, you always try your best to find the combination of 7-packs and 13-packs that will meet your customer’s thirst, for the least amount of hard-earned money – in that case, a 7-pack and a 13-pack.

To be extra clear, the goal is to find a combination of 7- and 13-packs containing at least as many bottles as requested, with a total number of bottles as close as possible to the amount requested.

But the unquenchable thirst of the population of Bizzarostan has been increasing lately, which is making your job harder. How would you know on top of your head what’s the best combination for a hundred bottles of Beer? Having great faith in the wonders of modern technology, you decide it’s time to write an application to find that ideal combination of beer packs.

I got a rather brute-force working solution already, which I will share in the next few days. This may be massive overkill, but that’s also a problem the Microsoft Solver Foundation can handle fairly easily, so we’ll look into that as well. I have this nagging feeling that there is an elegant recursive solution to the problem, but couldn’t write anything clever so far; if you have thoughts, please share them in the comments!

PS: no, I haven’t started working for a company that manufacture 7-packs of beers, it’s a transposition of a real-world, analogous problem.

PPS: I think this is also the closest I ever got to seeing a real application of the FizzBuzz problem in the real world.

26. June 2011 17:06

I have been digging into the Task Parallel library lately, and enjoying it a lot. As an exercise, I wondered if I could implement the classic FizzBuzz problem, using only Tasks, no loop-related keyword, and no method or property. To enforce this is, we’ll get FizzBuzz to run in the Main() method of a simple console, using only variables created locally.

Note: this is clearly a totally preposterous way to use the Task Parallel library. There is absolutely no benefit in using it in this context, I am doing this only for the sake of exploring how tasks work.

So how would we go about that?

A Task represents an asynchronous operation; it wraps a block of code, waiting to be executed. For instance, the following code queues up work to print out “Starting” to the console, and begins execution when we request the Task to start:

private static void Main(string[] args)
{
() =>
{
Console.WriteLine("Starting");
});
}

We clearly need something more for FizzBuzz. If we want to avoid looping constructs, we need to have a form of recursion going on, so that we can work on increasing integers, until we reach the limit we set to our FizzBuzz.

Fortunately, Tasks are about more than simply executing a block of code; they can be composed, defining what tasks can be started when some precursor tasks are finished. In particular, Tasks allow Continuations: what to do once a specific task terminates can be defined, by using Task.ContinueWith(), as in this example:

private static void Main(string[] args)
{
() =>
{
Console.WriteLine("Starting");
});

() =>
{
});

}

Here we define our root task, still printing “Starting”, and another task, which will print “Next task!”, and we pass that nextTask as a follow-up task to the rootTask via ContinueWith. Running this code will execute first the rootTask, and upon completion, kickstart the second one, and print both expected lines to the Console.

More...

#### Need help with F#?

The premier team for
F# training & consulting.