Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding byref, ref and &

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:

  1. 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?

  2. 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.

  3. 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.

  4. 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?

  5. 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
    
like image 930
Andry Avatar asked Feb 17 '11 11:02

Andry


People also ask

What is by Val and by ref?

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.

Is C# ByRef or ByVal?

C# Passing arguments by default is ByRef instead of ByVal.

How are arguments passed by value or by reference?

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.

How are arguments passed using the ByRef method?

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.


1 Answers

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...).

like image 154
Tomas Petricek Avatar answered Oct 16 '22 20:10

Tomas Petricek