Reputation: 22133
let iter2D (map: 'T byref -> unit) (arr: 'T[][]) =
for y = 0 to arr.Length - 1 do
let row = arr.[y]
for x = 0 to row.Length - 1 do
let mutable elem = arr.[y].[x]
map &elem
The last line has: "The address of the variable 'elem' cannot be used at this point." What's wrong?
Upvotes: 4
Views: 388
Reputation: 243051
In F# 'T byref
appears as a regular type, but under the cover, it is not - it corresponds to ref
and out
parameters in C# and those are special annotations on method arguments. This is why 'T byref
is a bit odd in F#.
I think you won't be able to use it through ordinary F# functions, because a function T1 -> T2
is compiled as FSharpFunc<T1, T2>
with a method T2 Invoke(T1 arg)
- and you cannot pass the byref
type to generics (as it is not a real type).
A workaround is to define your own delegate that has byref
type:
type FastAction<'T> = delegate of 'T byref -> unit
With this, you can write iter2D
that iterates directly over the array:
let iter2D (map:FastAction<'T>) (arr: 'T[][]) =
for y = 0 to arr.Length - 1 do
let row = arr.[y]
for x = 0 to row.Length - 1 do
map.Invoke(&arr.[y].[x])
The following will then mutate the value inside the array:
let arr = [| [| 0 |] |]
iter2D (FastAction(fun a -> a <- 10)) arr
Upvotes: 8