Understanding byref, ref and &

.net, byref, f#, parameter-passing, reference

Solution

Ref keyword Yes, when you write `let a = ref 10` you're essentially writing `let a = new Ref<int>(10)` where the `Ref<T>` type has a mutable field `Value`.

Access value The `:=` and `!` operators are just shortcuts for writing:

a.Value <- 10  // same as writing: a := 10
a.Value        // same as writing: !a

ByRef is a special type that can be (reasonably) used only in method parameters. It means that the argument should be essentially a pointer to some memory location (allocated on heap or stack). It corresponds to `out` and `ref` modifiers in C#. Note that you cannot create local variable of this type.

The & operator is a way to create a value (a pointer) that can be passed as an argument to a function/method expecting a `byref` type.

Calling functions the example with `byref` works because you're passing the method a reference to a local mutable variable. Via the reference, the method can change the value stored in that variable.

The following doesn't work:

let a = 10            // Note: You don't even need 'mutable' here
bar.Increment(ref a)  

The reason is that you're creating a new instance of `Ref<int>` and you're copying the value of `a` into this instance. The `Increment` method then modifies the value stored on heap in the instance of `Ref<int>`, but you don't have a reference to this object anymore.

let a = ref 10
bar.Increment(a)  

This works, because `a` is a value of type `Ref<int>` and you're passing a pointer to the heap-allocated instance to `Increment` and then get the value from heap-allocated reference cell using `!a`.

(You can use values created using `ref` as arguments for `byref` because the compiler handles this case specially - it will automatically take reference of the `Value` field because this is a useful scenario...).

Problem

Well, I came to understand that F# is able to manage references (some sort of C++ like references). This enables the possibilities to change value of parameters passed in functions and also enables the programmer to return more than a single value. However here's what I need to know: Ref keyword: The keyword `ref` is used to create, from a value, a reference to that value of the inferred type. So ``` let myref = ref 10 ``` This means that F# will create an object of type `Ref<int>` putting there (in the mutable field) my `int 10`. OK. So I assume that `ref` is used to create instances of the `Ref<'a>` type. Is it correct? Access value: In order to access a value stored in reference I can do this: ``` let myref = ref 10 let myval = myref.Value let myval2 = !myref ``` While the `:=` operator just lets me edit the value like this: ``` let myref = ref 10 myref.Value <- 30 myref := 40 ``` So `!` (Bang) dereferences my reference. And `:=` edit it. I suppose this is correct too. The & operator: What does this operator do? Is it to be applied to a reference type? No, I guess it must be applied to a mutable value and this returns what? The reference? The address? If using interactive: ``` let mutable mutvar = 10;; &a;; ``` The last line throws an error so I do not understand what the `&` operator is for. ByRef: What about `byref`? That's very important to me, but I realize I do not understand it. I understand it is used in function regarding parameter passing. One uses byref when he wants that the passed value can be edited (this is a bit against the functional languages' philosophy but f# is something more than that). Consider the following: ``` let myfunc (x: int byref) = x <- x + 10 ``` This is strange. I know that if you have a reference `let myref = ref 10` and then do this to edit the value: `myref <- 10` it arises an error because it should be like this: `myref := 10`. However, the fact that in that function I can edit `x` using the `<-` operator means that `x` is not a reference, right? If I assume that `x` is not a reference, then I assume also that, in functions, when using `byref` on a parameter, that parameter can have the mutable syntax applied to. So it is just a matter of syntax, if I assume this I am OK, and, in fact, everything works (no compiler errors). However, what is `x`? Calling functions: How can I use a function utilizing byref parameters? The `&` operator is involved but could you explain this better please? In this article: MSDN Parameters and Arguments the following example is provided: ``` type Incrementor(z) = member this.Increment(i : int byref) = i <- i + z let incrementor = new Incrementor(1) let mutable x = 10 // A: Not recommended: Does not actually increment the variable. (Me: why?) incrementor.Increment(ref x) // Prints 10. printfn "%d" x let mutable y = 10 incrementor.Increment(&y) (* Me: & what does it return? *) // Prints 11. printfn "%d" y let refInt = ref 10 incrementor.Increment(refInt) (* Why does it not work in A, but here it does? *) // Prints 11. printfn "%d" !refInt ```

Original source