F#: позвольте изменяемый по сравнению с касательно

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

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

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

Спасибо!

78
задан William Jockusch 28 November 2018 в 18:18
поделиться

4 ответа

Я могу только поддержать то, что сказал 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!
128
ответ дан 24 November 2019 в 10:33
поделиться

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

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

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

18
ответ дан 24 November 2019 в 10:33
поделиться

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

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

4
ответ дан 24 November 2019 в 10:33
поделиться

Вы можете взглянуть на раздел Mutable Data в викиучебнике.

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

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

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

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

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

3
ответ дан 24 November 2019 в 10:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: