Inside F#

Brian's thoughts on F# and .NET

Archive for January, 2011

Gotcha explained

Posted by Brian on January 28, 2011

Last time I posted a “gotcha” snippet, asking what this F# code prints:

    type MyVector(x:int, y:int, z:int) =

        // expose the values as an array
        member this.Values = [| x; y; z |]

    let v = new MyVector(1,2,3)
    v.Values.[0] <- 42
    printfn "%d" v.Values.[0]

It prints “1”.  To see why, let’s look at the corresponding C# code, in all its verbosity:

    class MyVector

    {
        int x, y, z;
        public MyVector(int x, int y, int z)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }
        // expose the values as an array
        public int[] Values
        {
            get { return new[] { x, y, z }; }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var v = new MyVector(1, 2, 3);
            v.Values[0] = 42;
            System.Console.WriteLine(v.Values[0]);
        }
    }

The C# code, being more explicit, makes things a little more obvious.  “Values” is a getter property, whose body creates a new array, and so every time you refer to “.Values”, a fresh array is created that contains the 3 integers that were passed into the constructor.  So the line that assigns the value 42 assigns it into a fresh array that is then immediately dropped on the floor.

This probably isn’t what is desired.  If we want “Values” to expose a single instance of a mutable array, then we can easily do so, by creating that array instance in the class constructor and returning that same instance each time people refer to the property.  In C#:

    class MyVector

    {
        int[] a;
        public MyVector(int x, int y, int z)
        {
            this.a = new[] { x, y, z };
        }
        // expose the values as an array
        public int[] Values
        {
            get { return a; }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var v = new MyVector(1, 2, 3);
            v.Values[0] = 42;
            System.Console.WriteLine(v.Values[0]);
        }
    }

and in F#:

    type MyVector(x:int, y:int, z:int) =

        let a = [| x; y; z |]
        // expose the values as an array
        member this.Values = a

    let v = new MyVector(1,2,3)
    v.Values.[0] <- 42
    printfn "%d" v.Values.[0]

I see people occasionally stumble on this in a variety of ways; the fact that F# property getter syntax (and overall syntax) is so succinct makes it easier to forget that the body of the member is code that will run each time the member is referenced.  One-time initialization should be moved to the constructor (the let/do section prior to the members; see this blog for a primer on the F# class/interface syntax).

Every language has its own little gotchas; at work those on the C# team still fall into the trap described here, and so it is fun to josh each other about the minor warts in our respective languages.  :)

Advertisements

Posted in Uncategorized | 4 Comments »

Come work on F#!

Posted by Brian on January 26, 2011

In case you haven’t heard, the F# team is hiring.  Want to work in Redmond as an F# developer, or a program manager, or a different developer?  (Or perhaps just search with keyword “F#”, for other F#-related jobs at Microsoft.)  See also Don’s blogs for info on applying.  There’s also a contract position in the UK for applied F#.

Since I dislike code-free blogs, I’ll leave you with a quick code snippet.  Ask yourself, what does this code print?  (Then try it.)

    type MyVector(x:int, y:int, z:int) =

        // expose the values as an array
        member this.Values = [| x; y; z |]

    let v = new MyVector(1,2,3)
    v.Values.[0] <- 42
    printfn "%d" v.Values.[0]

A hint: it illustrates a “gotcha” people sometimes hit when first learning the syntax for writing F# property getters.

Posted in Uncategorized | 4 Comments »