2

I'm just wondering if somebody can explain to me how to pass reference cells to functions that are not class members. I've been following the msdn page msdn reference cells

I have the following code:

let myint = ref 32
let mutable myint2 = 23

type addone() = 
    member t.myadd1func (x:int byref) = 
        x <- x + 1

let myadd1func (x:int byref) = 
    x <- x + 1

let adder = new addone()

adder.myadd1func myint
// myadd1func myint <---- this line does not compile

myadd1func &myint2 // <----- this line does though


printfn "%d" !myint
printfn "%d" myint2

My question is... what is the fundamental difference between the call I am making to the "Myadd1func" method on the class and the "myadd1func" function defined after it?

As I write this, I'm guessing that the function doesn't like having .net object references being passed to it as this might break compatibility with other IL components?? I don't mind using a mutable value, I just like to understand these things.

Thanks

Jimmy
  • 6,001
  • 1
  • 22
  • 21
  • You might also find this interesting. http://stackoverflow.com/questions/3221200/f-let-mutable-vs-ref – gradbot Feb 03 '11 at 16:31

2 Answers2

5

I think the byref type in F# should be used only for interoperability purpsoes where the existing features (as explained by kvb) are good enough. If you want to declare a function that modifies some argument passed to it, I would just use ordinary reference cell (e.g. int ref type):

let myadd1func (x:int ref) =
  x := !x + 1 

let myint = ref 10
myadd1func myint

This may be slightly slower than using byref type (together with local mutable value), but I don't think it is needed very often in functional style, so it should be fine.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
1

This is explained in the Type-directed Conversions at Member Invocations section of the F# specification. For interoperability with other .NET components, ref cells can be passed to members taking byref parameters and the compiler will automatically treat it as the dereferencing of the cell's contents field. However, this isn't done for let-bound functions, and you should directly use the addressof operator (&). You can still use a ref cell, but you have to explicitly dereference the contents field yourself, so this should work in your example: myadd1func &myint.contents

kvb
  • 54,864
  • 2
  • 91
  • 133
  • Thanks very much for pointing me at the F# spec - I think there is other stuff in there that will help me when I come across situations like these. – Jimmy Feb 03 '11 at 17:04