Phil Trelford's Array
POKE 36879, 255

Fixed Width Data Files

May 6, 2013 14:16 by phil

Scanning over Alvin Ashcraft’s excellent Morning Dew (a must read for .Net devs as is Chris Alcock’s Morning Brew), I came across a short article from Richard Carr on writing Fixed Width Data Files using C#.

Richard creates a class that inherits from StreamWriter, and all-in it’s just over 50 lines of idiomatic C# code:

using System;
using System.IO;
using System.Text;

public class FixedWidthWriter : StreamWriter
{
    public int[] Widths { get; set; }

    public char NonDataCharacter { get; set; }

    public FixedWidthWriter(
          int[] widths, string path, bool append, Encoding encoding)
        : base(path, append, encoding)
    {
        NonDataCharacter = ' ';
        Widths = widths;
    }

    public FixedWidthWriter(int[] widths, string file)
        : this(widths, file, false, Encoding.UTF8) { }

    public FixedWidthWriter(int[] widths, string file, bool append)
        : this(widths, file, append, Encoding.UTF8) { }

    public void WriteLine(string[] data)
    {
        if (data.Length > Widths.Length)
            throw new 
                InvalidOperationException("The data has too many elements.");

        for (int i = 0; i < data.Length; i++)
        {
            WriteField(data[i], Widths[i]);
        }
        WriteLine();
    }

    private void WriteField(string datum, int width)
    {
        char[] characters = datum.ToCharArray();
        if (characters.Length > width)
        {
            Write(characters, 0, width);
        }
        else
        {
            Write(characters);
            Write(new string(NonDataCharacter, width - characters.Length));
        }
    }
}

As you’d probably guess the same functionality takes half the lines to express in F#:

open System
open System.IO
open System.Text

type FixedWidthWriter(widths:int[], path:string, append, encoding) =
    inherit StreamWriter(path, append, encoding)
    member val Widths = widths with get, set
    member val NonDataCharacter = ' '  with get, set
    new(widths, file) = 
        new FixedWidthWriter(widths, file, false, Encoding.UTF8)
    new(widths, file, append) =
        new FixedWidthWriter(widths, file, append, Encoding.UTF8)
    member this.WriteLine(data:string[]) =
        if data.Length > this.Widths.Length
        then invalidOp "The data has too many elements."
        for i = 0 to data.Length-1 do      
            this.WriteField(data.[i], this.Widths.[i])
        base.WriteLine()
    member private this.WriteField(datum:string, width) =
        let xs = datum.ToCharArray()
        if xs.Length > width
        then base.Write(xs, 0, width)
        else        
            base.Write(xs)
            base.Write(String(this.NonDataCharacter, width - xs.Length))

The C# implementation uses classes and inheritance. In F# we’d typically favour composition over inheritance and start with the simplest possible thing that works, which in this case is a function that takes a file path, widths and the lines to write:

let WriteFixedWidth (path:string) (widths:int[]) (lines:string[] seq) =
    let pad = ' '
    use stream = new StreamWriter(path)
    let WriteField (datum:string) width =
        let xs = datum.ToCharArray()
        if xs.Length > width
        then stream.Write(xs, 0, width)
        else        
            stream.Write(xs)
            stream.Write(String(pad, width - xs.Length))
    for line in lines do
        for i = 0 to widths.Length-1 do 
            WriteField line.[i] widths.[i]
        stream.WriteLine()

The function is about half the size again and more closely follows YAGNI. To test it we can simply write:

let widths = [|20; 7; 6|]
[
[|"Company"; "Spend"; "Rating"|]
[|"Quality Foods Limited"; "1000000"; "Gold"|]
[|"The Pieman"; "50000"; "Silver"|]
[|"Bill's Fruit and Veg"; "10000"; "Bronze"|]
]
|> WriteFixedWidth "c:\\test.txt" widths

Does the language you chose make a difference?
Tags:
Categories: C# | F# | .Net | Architecture
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed

Fractal Zoom in Colour

April 28, 2013 05:58 by phil

A few years back I put together a simple Fractal Zoom in Silverlight using gray scales.

Time for a little makeover with color:


Hold down the mouse button over the Mandelbrot and move the mouse to highlight a rectangle, then release the mouse button to zoom in on that area.

Implementation

To get a nice colour progression I used the HSB color circle:

let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5

Then created a colour lookup table using a list comprehension:

[|for i in 0..maxIteration ->
    let n = float i / float maxIteration
    let H,S,L = 0.95 + (10.0 * n), 0.6, 0.5
    let H = H - floor H
    let r,g,b = RGB.FromHSL(H,S,L)
    0xff000000 + (r <<< 16) + (g <<< 8) + b|]

For the HSL to RGB conversion I converted Colin Eberhardt’s accepted Stack Overflow answer from C# to F#:

C# F#
double v;
double r, g, b;
if (A > 1.0)
A = 1.0;

r = L;   // default to gray
g = L;
b = L;
v = 
   (L <= 0.5) 
   ? (L * (1.0 + S)) 
   : (L + S - L * S);
if (v > 0)
{
    double m;
    double sv;
    int sextant;
    double fract, vsf, mid1, mid2;

    m = L + L - v;
    sv = (v - m) / v;
    H *= 6.0;
    sextant = (int)H;
    fract = H - sextant;
    vsf = v * sv * fract;
    mid1 = m + vsf;
    mid2 = v - vsf;
    switch (sextant)
    {
       case 0:
        r = v;
        g = mid1;
        b = m;
        break;
       case 1:
        r = mid2;
        g = v;
        b = m;
        break;
       case 2:
        r = m;
        g = v;
        b = mid1;
        break;
       case 3:
        r = m;
        g = mid2;
        b = v;
        break;
       case 4:
        r = mid1;
        g = m;
        b = v;
        break;
       case 5:
        r = v;
        g = m;
        b = mid2;
        break;
    }
}
ColorRGB rgb = new ColorRGB();
rgb.R = Convert.ToByte(r * 255.0f);
rgb.G = Convert.ToByte(g * 255.0f);
rgb.B = Convert.ToByte(b * 255.0f);
rgb.A = Convert.ToByte(A * 255.0f);
return rgb;
let v = 
    if (L <= 0.5) 
    then (L * (1.0 + S)) 
    else (L + S - L * S)
if v > 0.0 then                
    let m = L + L - v;
    let sv = (v - m) / v;
    let H = H * 6.0;
    let sextant = int H
    let fract = H - float sextant
    let vsf = v * sv * fract;
    let mid1 = m + vsf;
    let mid2 = v - vsf;
    match sextant with
    | 0 -> v, mid1, m
    | 1 -> mid2, v, m
    | 2 -> m, v, mid1
    | 3 -> m, mid2, v
    | 4 -> mid1, m, v
    | 5 -> v, m, mid2
    | _ -> L, L, L
else L, L, L
|> fun (r,g,b) –> 
   byte(r*255.),
   byte(g*255.),
   byte(b*255.)

Voila, happy zooming :)


Tags:
Categories: F# | C# | .Net | Silverlight
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

Foq It Easy

April 24, 2013 08:10 by phil

Foq is a .Net mocking library with first class support for F# and a cool sounding name. After 9 public releases, Foq is now mature and stable at version 0.9. What started as a 6 to 8 week project ended up more like a half-year project. At this point, I’d like to say a big thank you for the great feedback from the community, and specifically acknowledge the help and support of Mathias Brandewinder, Vasily Kirichenko, Niklas Bergius and Neil Danson. Yesterday the first Foq question appeared on Stack Overflow, thanks to Michael Newton.

F# makes unit testing easy with static method support in xUnit and NUnit, white space in method names and object expressions for mocking simple interfaces:

let [<Test>] ``at 15:00 the sun image should be expected`` () =
    let time = { new ITime with member mock.GetHour() = 15 }
    let calculator = ImageCalculator(time)
    let image = calculator.GetImageForTimeOfDay()
    Assert.AreEqual("sun.jpg",  image)

Foq provides a fluent interface for scaling up to larger interfaces like IList(T), where there are many members, but you may only be interested in specifying return values for a few of them:

let [<Test>] ``setup a method to always return true`` () =
    // Arrange
    let instance =
        Mock<IList>()
            .Setup(fun xs -> <@ xs.Contains(any()) @>).Returns(true)
            .Create()
    // Assert
    Assert.IsTrue(instance.Contains("Anything"))

Foq’s API is quite similar to Moq’s or FakeItEasy’s. Not only does it support LINQ expressions there’s F# Code Quotations too. I tend to think of Code Quotations like classic ASP code blocks <% .. %> for quoting code but with @’s <@ … @>. Code Quotations add a little syntactic noise but come with more expression types than LINQ expressions, so far example you can specify events as you would properties. If however you prefer your lambdas with less symbols then just open the Foq.Linq namespace instead.

Foq also provides some handy shortcuts like the Method method:

let [<Test>] ``setup a method to always return true`` () =
    // Arrange
    let instance =
        Mock<IList>.Method(fun xs -> <@ xs.Contains @>).Returns(true)
    // Assert
    Assert.IsTrue(instance.Contains("Anything"))

Note that even the arguments are omitted from the invocation of Contains for ease.

Where the Method method lets you set up a single method, the With method lets you setup multiple methods with a single method:

Mock<IList<char>>.With(fun xs ->
    <@ xs.Count --> 2 
       xs.Item(0) --> '0'
       xs.Item(1) --> '1'
       xs.Contains(any()) --> true
       xs.RemoveAt(2) ==> System.ArgumentOutOfRangeException()
    @>
)

Here a custom operator –-> is employed to signify returning a value from a member, and the ==> operator raising an exception. For setting up many members, letting go of the heavy fluent interface helps let the actual intent shine through.

Sometimes you just want an instance of an interface mocked which just follows the defaults, and like Moq you can easily specify Mock<T>.Of:

let [<Test>] ``order sends mail if unfilled`` () =
    // setup data
    let order = Order("TALISKER", 51)
    let mailer = Mock.Of<MailService>()
    order.SetMailer(mailer)
    // exercise
    order.Fill(Mock.Of<Warehouse>())
    // verify
    verify <@ mailer.Send(any()) @> once

The mock function lets F# type inference worry about the types for you:

let [<Test>] ``order sends mail if unfilled`` () =
    // setup data
    let order = Order("TALISKER", 51)
    let mailer = mock()
    order.SetMailer(mailer)
    // exercise
    order.Fill(mock())
    // verify
    verify <@ mailer.Send(any()) @> once

Foq support verification of calls as seen above, or you can specify expectations against members and even specific sequence of calls, as you would with the With method:

let xs = Mock<IList<int>>.ExpectSequence(fun xs ->
    <@
        xs.Clear()
        xs.[any()] --> any()
        xs.[any()] <- any()
        xs.Count --> any()
        xs.Contains(any()) --> any()
    @>)

Want to see some more examples, you got it:

All you need to play with Foq is to open an F# project in Visual Studio, Xamarin Studio or Tsunami and pull the Foq library from Nuget or simply reference Foq.fs in your project. Looking forward to more releases and more feedback :)


Tags:
Categories: F# | C# | .Net
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed