Reputation: 21767
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
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
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