F#:让mutable与ref

J C*_*per 78 f# mutable

首先,我承认这个问题可能是重复的; 请告诉我

我很好奇当需要可变性时,对于那些情况,一般的"最佳实践"是什么.F#似乎为此提供了两种工具:let mutable绑定,它似乎像"大多数"语言中的变量一样工作,而参考单元(使用ref函数创建)需要显式解除引用才能使用.

有一对夫妇的情况下,其中一个是"被迫"转化为一种或另一种:.NET互操作倾向于使用可变带<-,并在工作流程的计算必须使用ref:=.所以这些案例非常明确,但我很好奇在这些场景之外创建自己的可变变量时该怎么做.一种风格比另一种风格有什么优势?(也许对实施的进一步了解会有所帮助.)

谢谢!

Tom*_*cek 128

我只能支持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 }
Run Code Online (Sandbox Code Playgroud)

两种方法之间的显着差异是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!
Run Code Online (Sandbox Code Playgroud)

  • @jaromey是的,我了解我从根本上不同意eric。在考虑什么是“最佳实践”时,您不能忽视性能方面的考虑。人们通常认为性能无关紧要,但是由于千个实施细节导致的运行速度太慢,导致软件运行缓慢。 (4认同)
  • 只是提醒一下:在堆栈上或堆上是一个实现细节,与问题不完全相关(但仍然是很好的答案) (2认同)
  • 我会说,在确定最佳实践是什么时,了解是否会引起堆分配和收集的开销非常重要。 (2认同)
  • @jackmott 查看 Eric Lippert 撰写的这篇文章,名为 [堆栈是一个实现细节](https://blogs.msdn.microsoft.com/ericlippert/2009/04/27/the-stack-is-an-implementation-detail -第一部分/) (2认同)

gra*_*bot 18

相关问题: "你提到闭包不能捕获局部可变值,所以你需要使用ref.原因是闭包中捕获的可变值需要在堆上分配(因为闭包是在堆)." 来自F#ref-mutable vars vs object fields

我认为let mutable比参考细胞更受欢迎.我个人只在需要时才使用参考单元格.

由于递归和尾调用,我编写的大多数代码都不使用可变变量.如果我有一组可变数据我使用记录.对于我let mutable用来制作私有可变变量的对象.我只使用参考单元来进行闭包,通常是事件.


And*_*rii 7

正如在描述这个MSDN博客文章在部分简化使用可变值,你不再需要lambda表达式REF细胞.所以一般来说你根本不再需要它们.


Mau*_*Mau 5

Brian 的这篇文章或许可以提供答案。

可变值易于使用且高效(无需包装),但无法在 lambda 中捕获。参考单元可以被捕获,但冗长且效率较低(? - 不确定这一点)。

  • 这种情况已经改变,因为在大多数情况下可以捕获 F# 4.0 mutable,并且现在对 ref 的需求少了很多。 (2认同)