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
The advantage of passing an argument ByRef is that the procedure can return a value to the calling code through that argument. The advantage of passing an argument ByVal is that it protects a variable from being changed by the procedure.
C# Passing arguments by default is ByRef instead of ByVal.
When you pass an argument by reference, you pass a pointer to the value in memory. The function operates on the argument. When a function changes the value of an argument passed by reference, the original value changes. When you pass an argument by value, you pass a copy of the value in memory.
You pass an argument by reference by specifying the ByRef keyword for the corresponding parameter in the procedure definition. When you use this passing mechanism, Visual Basic gives the procedure a direct reference to the underlying programming element in the calling code.
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...).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With