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.