首页 文章

F#:让mutable与ref

提问于
浏览
71

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

我很好奇普通"best practice"对于那些需要可变性的情况 . F#似乎为此提供了两种工具: let mutable 绑定,它似乎像"most"语言中的变量一样工作,而参考单元(使用 ref 函数创建)需要显式取消引用才能使用 .

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

谢谢!

5 回答

  • 16

    我只能支持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!
    
  • 5

    Related Question: "You mentioned that local mutable values cannot be captured by a closure, so you need to use ref instead. The reason for this is that mutable values captured in the closure need to be allocated on the heap (because closure is allocated on the heap)."来自F# ref-mutable vars vs object fields

    我认为 let mutable 优于参考细胞 . 我个人只在需要时才使用参考单元格 .

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

  • 3

    this MSDN Blog article中第 Simplified use of mutable values 节所述,您不再需要为lambdas使用ref单元格 . 所以一般来说你根本不再需要它们 .

  • 4

    布莱恩的This article可能会给出答案 .

    Mutables易于使用且高效(无包装),但无法在lambdas中捕获 . 可以捕获参考细胞,但是冗长且效率较低(? - 不确定) .

  • 112

    您可能需要查看wikibook中的Mutable Data部分 .

    为方便起见,这里有一些相关的引用:

    mutable关键字经常与记录类型一起使用以创建可变记录可变变量有些限制:在定义它们的函数范围之外,不可访问变量 . 具体地说,这意味着不可能在另一个函数的子函数中引用可变的 . Ref细胞克服了mutables的一些局限性 . 事实上,ref单元格是非常简单的数据类型,它包含记录类型中的可变字段 . 由于ref cell是在堆上分配的,因此它们可以在多个函数之间共享

相关问题