F #: пусть изменчивый против ref - PullRequest
76 голосов
/ 11 июля 2010

Во-первых, я признаю возможность того, что этот вопрос может быть дубликатом; просто дай мне знать.

Мне любопытно, какова общая "лучшая практика" для тех ситуаций, когда требуется изменчивость. Кажется, F # предлагает два средства для этого: привязка let mutable, которая, похоже, работает как переменные в «большинстве» языков, и ячейка ссылки (созданная с помощью функции ref), для которой требуется явная разыменование.

Есть пара случаев, когда один «принудительно» переходит в один или другой: .NET-взаимодействие имеет тенденцию использовать изменяемый с <-, а в вычислениях рабочего процесса нужно использовать ref с :=. Таким образом, эти случаи довольно ясны, но мне любопытно, что делать, когда я создаю свои изменяемые переменные вне этих сценариев. Какое преимущество имеет один стиль над другим? (Возможно, дальнейшее понимание реализации поможет.)

Спасибо!

Ответы [ 5 ]

124 голосов
/ 11 июля 2010

Я могу поддержать только то, что сказал 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!
18 голосов
/ 11 июля 2010

Связанный вопрос:"Вы упомянули, что локальные изменяемые значения не могут быть захвачены замыканием, поэтому вместо этого нужно использовать ref. Причина этого заключается в том, что изменяемые значения, захваченные в замыкании, должны быть распределеныв куче (потому что закрытие выделяется в куче). "из F # ref-mutable vars vs поля объекта

Я думаю, let mutable предпочтительнее, чем ссылочные ячейки.Лично я использую ссылочные ячейки только тогда, когда они требуются.

Большая часть кода, который я пишу, не использует изменяемые переменные благодаря рекурсии и хвостовым вызовам.Если у меня есть группа изменяемых данных, я использую запись.Для объектов я использую let mutable, чтобы сделать закрытые изменяемые переменные.Я действительно использую ссылочные ячейки только для замыканий, обычно для событий.

7 голосов
/ 04 сентября 2016

Как описано в этой статье блога MSDN в разделе Упрощенное использование изменяемых значений , вам больше не нужны ссылочные ячейки для лямбд. В общем, они вам больше не нужны.

4 голосов
/ 11 июля 2010

Эта статья Брайана может дать ответ.

Изменяемые таблицы просты в использовании и эффективны (без переноса), но не могут быть записаны в лямбдах.Ячейки справки можно захватить, но они многословны и менее эффективны (? - не уверены в этом).

3 голосов
/ 11 июля 2010

Возможно, вы захотите взглянуть на раздел Изменяемые данные в вики-книге.

Для удобства приведем несколько соответствующих цитат:

Часто используемое ключевое слово с типами записей для создания изменчивых записи

Изменчивые переменные несколько ограниченный: изменяемые файлы недоступны вне рамок функции где они определены. В частности, это означает, что невозможно ссылаться на изменяемый в подфункции другой функции.

Ячейки Ref обходят некоторые из ограничения изменчивости. На самом деле, ссылка ячейки очень простой тип данных, который обернуть изменяемое поле в записи тип.

Поскольку ячейки ref расположены на куча, они могут быть разделены между несколько функций

...