Во-первых, я признаю возможность того, что этот вопрос может быть дубликатом; просто дай мне знать.
Мне любопытно, какова общая «лучшая практика» для тех ситуаций, когда желательна изменчивость. Кажется, что F # предлагает для этого две возможности: let mutable
привязку, которая работает как переменные в «большинстве» языков, и ссылочная ячейка (созданная с помощью ref
функции), для использования которой требуется явное разыменование.
Есть пара случаев, когда одно «принудительно» совпадает с тем или другим: взаимодействие .NET имеет тенденцию использовать изменяемый с <-
и в вычислениях рабочего процесса, которые необходимо использовать ref
с :=
. Так что эти случаи довольно ясны, но мне любопытно, что делать при создании моих собственных изменяемых переменных вне этих сценариев. Какое преимущество у одного стиля перед другим? (Возможно, поможет более глубокое понимание реализации.)
Благодаря!
Ответы:
Я могу только поддержать то, что сказал градбот - я предпочитаю, когда мне нужна мутация
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!
источник
Связанный вопрос: «Вы упомянули, что локальные изменяемые значения не могут быть захвачены замыканием, поэтому вместо этого вам нужно использовать ref. Причина этого в том, что изменяемые значения, захваченные в замыкании, должны быть размещены в куче (поскольку закрытие выделяется на куча) ". из F # ref-mutable vars против полей объекта
я думаю
let mutable
предпочтительнее ссылочных ячеек. Я лично использую ссылочные ячейки только тогда, когда они требуются.Большая часть кода, который я пишу, не использует изменяемые переменные благодаря рекурсии и хвостовым вызовам. Если у меня есть группа изменяемых данных, я использую запись. Для объектов, которые я использую
let mutable
для создания частных изменяемых переменных. Я действительно использую ссылочные ячейки только для замыканий, как правило, событий.источник
Как описано в этой статье блога MSDN в разделе « Упрощенное использование изменяемых значений» , вам больше не нужны ячейки ссылки для лямбда-выражений. Так что в общем они вам вообще больше не нужны.
источник
Эта статья Брайана может дать ответ.
Изменяемые элементы просты в использовании и эффективны (без упаковки), но не могут быть записаны в лямбдах. Референсные ячейки могут быть захвачены, но они подробны и менее эффективны (? - не уверен в этом).
источник
Возможно, вы захотите взглянуть на раздел «Изменяемые данные » в викиучебнике.
Для удобства приведем несколько уместных цитат:
источник