Использование ref
в вашем примере может быть не совсем тем, что вы хотели написать:
let modify (data:int byref) = data <- 10
let foo() =
let mutable n = 15 // Note: Compiles without 'mutable'
modify (ref n)
printfn "%d" n // Prints '10'!!
Вы, вероятно, хотели что-то вроде этого:
let foo() =
let n = ref 15
modify n
printfn "%d" (!n) // Prints '15'
Так в чем же разница? ref
- это функция, которая принимает значение и создает выделенную для кучи ячейку ссылки. Во втором примере, тип n
есть ref<int>
, который является ссылкой на ячейку. F # позволяет передавать ссылочные ячейки в качестве аргументов byref
параметрам - в этом случае он создает указатель на поле объекта, выделенного в куче (ссылочная ячейка).
Во втором примере мы создаем ссылочную ячейку, передаем указатель на ссылочную ячейку в функцию modify
и затем используем синтаксис !<ref>
для получения значения из ссылочной ячейки. В первом примере мы создаем новую ссылочную ячейку при вызове функции modify
(а значение n
копируется из стека в выделенную кучу ячейку). Ячейка не используется после вызова (и значение n
остается 15)
С другой стороны, переменная mutable
просто сохраняется в стеке и может быть видоизменена. Основное отличие состоит в том, что ref
всегда выделяется кучей - использование mutable
может быть (в принципе) немного быстрее, потому что вызываемая функция, принимающая byref
, напрямую изменяет значение в стеке.