Inside F#

Brian's thoughts on F# and .NET

The F# “ref” type

Posted by Brian on November 9, 2008

I haven’t written much about the F# "ref" type, as it’s not used all that often.  But I have an interesting blog entry coming up that needs "ref", so I thought I should write a short blog entry on the topic to get the basics out of the way.

Values and Variables; "let" and "let mutable"

In F#, immutability is the default; when I write

    let x = 1

the symbol ‘x’ is permanently bound to the value 1 for the whole scope of ‘x’.

F# introduces the more verbose "let mutable" syntax for creating mutable variables, as in

    let mutable x = 1
    printfn "%d"// 1
    x <- x + 1
    printfn "%d"// 2

The value of a mutable variable can be accessed just by referring to the variable name (e.g. "x"), and an assignment operator "<-" mutates the variable’s value.

That information is likely "old hat" to you.  But did you know there is another way to do mutability in F#?

The "ref" type

F# has another construct for mutable state that it inherits from OCaml: refs.  A "ref" is a mutable heap-allocated cell that holds one piece of data.  Here’s a short example:

    let y = ref 1
    printfn "%d" !y  // 1
    y := !y + 1
    printfn "%d" !y  // 2

In that snippet, "y" has type "int ref" (a.k.a. "Ref<int>").  There are three notable entities here:

  • The function "ref", which allocates a new ref cell given an initial value,
  • The prefix operator ‘!’, which dereferences a ref cell (returns the value stored inside it), and
  • The ref assignment operator ":=", which updates the value stored in the ref cell.

The syntax is a little ugly in my opinion (especially when so many of us are now accustomed to ‘!’ meaning "not"), but it’s easy and straightforward to use.  For those who like to see a more operational definition of the construct, here is a possible implementation of a type that’s very similar to the one built-in to the F# library:

    type MyRef<‘a>(x:‘a)
        let mutable contents = x
        member this.Contents with get() = contents
                             and set(x) = contents <- x
    let ref x = 
        new MyRef<_>(x)
    let (:=) (x:MyRef<_>) y = 
        x.Contents <- y
    let (!) (x:MyRef<_>)
        x.Contents

(In fact, both in F# and OCaml, the built-in ref type uses a "record" as an implementation, but I have said very little about records on this blog, and didn’t want to explain one unfamiliar construct via another unfamiliar one, so here I chose to write "MyRef" as a class, instead.)  Straightforward, yes?

So of course this begs the question: if F# has "let mutable", when would I ever use "ref" (other than to author OCaml-compatible code)?  It turns out that in some situations you must use "ref" instead of "let mutable", and I’ll describe those situations… in the next blog entry.

Next time

Here is a teaser for next time, though.  What does the following C# code print?  Is it 0, 2, 4, 6, 8?  Perhaps you should run it and find out.

    List<Func<int>> actions = new List<Func<int>>(); 
    for (int i = 0; i < 5; ++i)
    { 
        actions.Add( () => i * 2 ); 
    } 
    foreach (var act in actions) 
    { 
        Console.WriteLine( act() ); 
    }

We’ll see how this C# code snippet relates to F# "ref" next time, too!

Advertisements

One Response to “The F# “ref” type”

  1. Jared said

    The C# code will print out all 10`s.  The reason being is the lambda expression lifts the variable i.  There is only a single copy of the variable i and the lambdas all execute after the loop is completed.  They will all operate on the final value of i which is 5.
     
    Note.  In VB the equivalent code will produce a warning due to the confusing nature of this exact scenario. 
     
    JaredPar
    http://blogs.msdn.com/jaredpar

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: