colinfang
colinfang

Reputation: 21767

Why am I not allowed to use reference cell as argument for byref parameter in let functions?

This doesn't work:

let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(xxx) // this expression was expected to have type
               // byref<int> but here has type int ref

But this works:

let incrementParam(a: int byref) = a <- a + 1
let mutable b = 30
incrementParam(&b)

as well as this:

type Incrementor =
    static member Increment(i : int byref) =
       i <- i + 1

let fff = ref 10
Incrementor.Increment(fff) 

Upvotes: 3

Views: 301

Answers (2)

Tomas Petricek
Tomas Petricek

Reputation: 243096

To add some details to the reference that Daniel pointed out, the problem is that the type 'T ref is not the same as the type 'T byref and so the compiler needs to insert some conversion (to take the address).

I think this is only supported for members, because this is the main scenario (calling COM interop methods etc.) and because implicit conversions generally compilcate type inference. The type-directed conversions are an easier case where the compiler already knows the required type ('T byref). I suppose that, if this was allowed on functions, the compiler might infer that the type of argument should actually be 'T ref.

If you want to get the first sample to work, you have to explicitly construct 'T byref by taking the address of the contents field:

let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(&xxx.contents)

Upvotes: 5

Daniel
Daniel

Reputation: 47914

Because the spec says so. See Type Directed Conversions at Member Invocations (emphasis mine), especially the following:

Note: These type-directed conversions are primarily for interoperability with existing member-based .NET libraries and do not apply at invocations of functions defined in modules or bound locally in expressions.

Upvotes: 6

Related Questions