Я могу поддержать только то, что сказал gradbot - когда мне нужна мутация, я предпочитаю let mutable
.
Относительно реализации и различий между двумя ячейками - ref
, по сути, реализованы очень простой записью, которая содержит изменяемое поле записи. Вы могли бы написать их легко самостоятельно:
type ref<'T> = // '
{ mutable value : 'T } // '
// the ref function, ! and := operators look like this:
let (!) (a:ref<_>) = a.value
let (:=) (a:ref<_>) v = a.value <- v
let ref v = { value = v }
Заметное различие между этими двумя подходами состоит в том, что let mutable
хранит изменяемое значение в стеке (как изменяемая переменная в C #), тогда как ref
хранит изменяемое значение в поле записи, выделенной для кучи. Это может оказать некоторое влияние на производительность, но у меня нет цифр ...
Благодаря этому к изменяемым значениям, использующим ref
, можно присваивать псевдонимы. Это означает, что вы можете создать два значения, ссылающихся на одно и то же изменяемое значение:
let a = ref 5 // allocates a new record on the heap
let b = a // b references the same record
b := 10 // modifies the value of 'a' as well!
let mutable a = 5 // mutable value on the stack
let mutable b = a // new mutable value initialized to current value of 'a'
b <- 10 // modifies the value of 'b' only!