F#:让可变与参考
首先,我承认这个问题可能是重复的; 只是让我知道。
我很好奇什么是一般的“最佳做法”是什么时候需要可变性的情况。 F#似乎为此提供了两个工具: let mutable
绑定,它似乎像“大多数”语言中的variables一样工作,而参考单元(使用ref
函数创build)需要使用明确的解引用。
有两种情况是“被迫”进入其中一种情况:.NET interop倾向于使用可变的<-
,在工作stream计算中,必须使用ref
:=
。 所以这些情况非常明确,但是我很好奇在这些场景之外创build自己的可变variables时该怎么做。 一种风格有什么优势? (也许进一步洞察实施将会有所帮助。)
谢谢! (对于“过度使用”引号感到抱歉。)
我只能支持gradbot说的 – 当我需要突变的时候,我更喜欢let mutable
。
关于两个ref
的实现和区别基本上是由一个非常简单的包含一个可变logging字段的logging实现的。 你可以很容易地写他们自己:
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#中的可变variables),而ref
将可变值存储在堆分配logging的字段中。 这可能会对性能有一些影响,但我没有任何数字…
由于这个原因,使用ref
可变值可以是别名 – 这意味着您可以创build两个引用相同可变值的值:
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 vs对象字段
我认为let mutable
比参考细胞let mutable
。 我个人只有在需要时才使用参考单元。
我写的大部分代码都不会使用可变variables,这要归功于recursion和尾部调用。 如果我有一组可变数据,我使用一个logging。 对于我使用let mutable
来制作私有的可变variables。 我只是真的使用参考单元来closures,一般是事件。
Brian的这篇文章可能会提供一个答案。
Mutables易于使用和高效(不包装),但不能在lambdas中捕获。 参考细胞可以被捕获,但是细节和效率较低(? – 不确定这一点)。
正如本 简化使用可变值部分中的MSDN博客文章中所述,不再需要lambda表的ref单元。 所以一般来说,你不再需要它们。
您可能需要查看wikibook中的可变数据部分。
为方便起见,这里有一些相关的引用:
可变关键字经常与loggingtypes一起使用来创build可变logging
可变variables有一定的局限性:在定义函数的范围之外,可变参数是不可访问的。 具体来说,这意味着它不可能在另一个函数的子函数中引用mutable。
Ref细胞解决了mutable的一些限制。 事实上,ref单元格是非常简单的数据types,它包含了一个loggingtypes中的可变字段。
由于ref单元在堆上分配,因此可以跨多个函数共享