Pointers in F#

F# supports references, allowing you to pass mutable values within your program. Let’s explore how references work in contrast to values with two functions: zeroval and zeroptr.

open System

// zeroval takes an int parameter, so arguments will be passed to it by value.
// zeroval will get a copy of ival distinct from the one in the calling function.
let zeroval (ival: int) =
    let mutable localIval = ival
    localIval <- 0

// zeroptr takes an int ref parameter, meaning that it takes a reference to an int.
// The ! operator in the function body then dereferences the reference.
// Assigning a value to a dereferenced reference changes the value at the referenced location.
let zeroptr (iptr: int ref) =
    iptr.Value <- 0

[<EntryPoint>]
let main argv =
    let mutable i = 1
    printfn "initial: %d" i

    zeroval i
    printfn "zeroval: %d" i

    // The ref keyword creates a reference to i
    zeroptr (ref i)
    printfn "zeroptr: %d" i

    // In F#, we can't directly print the memory address, 
    // but we can demonstrate that we're working with a reference
    let iRef = ref i
    printfn "reference: %A" iRef

    0 // return an integer exit code

zeroval doesn’t change the i in main, but zeroptr does because it has a reference to the memory location for that variable.

To run the program, save it as References.fs and use the F# compiler:

$ fsharpc References.fs
$ mono References.exe
initial: 1
zeroval: 1
zeroptr: 0
reference: {contents = 0}

Note that F# uses the term “reference” instead of “pointer”. The ref keyword creates a reference, and the ! operator dereferences it. The .Value property is used to get or set the value of a reference.

Also, F# doesn’t allow direct manipulation of memory addresses like in some other languages. Instead, it provides a safer, more abstract way of working with references.