Why am I not allowed to use a reference cell as an argument for the byref parameter in the let function?
This does not 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)
and:
type Incrementor =
static member Increment(i : int byref) =
i <- i + 1
let fff = ref 10
Incrementor.Increment(fff)
source to share
Because the spec says so. See Type Directed Conversions in Member Invocations (focus), especially the following:
Note. These type-oriented conversions are intended primarily for interoperability with existing .NET-based .NET libraries and do not apply to calls to functions defined in modules or bound locally in expressions.
source to share
To add some information to the link that Daniel pointed out, the problem is that the type is 'T ref
not the same as the type 'T byref
, so the compiler needs to insert some kind of conversion (to accept the address).
I think this is only supported for contributors, because this is the main scenario (calling COM interop methods, etc.) and because implicit conversions usually compile type inference. Type-oriented conversions are an easier case where the compiler already knows the required type ( 'T byref
). I suppose that if it were allowed for functions, the compiler could infer that the type of the argument should be 'T ref
.
If you want the first sample to work, you must explicitly build 'T byref
by taking the address of the field contents
:
let increment(i: int byref) = i <- i + 1
let xxx = ref 0
increment(&xxx.contents)
source to share