F# 从可变更改为 ref

F# Changing from mutable to ref

提问人:user1443098 提问时间:4/27/2017 更新时间:4/27/2017 访问量:312

问:

正在处理需要可变集的程序。当尝试将集合放入闭包中时,我收到一个错误:

let mutable donefiles : Set<FileRecord> = Set.empty
let filestodo = Set.difference parms.FileSpecs donefiles
let errorFile (file: FileRecord) =
    donefiles <- Set.add file donefiles

错误 40 可变变量“donefiles”以无效的方式使用。 可变变量无法通过闭包捕获。考虑消除 这种使用突变或使用堆分配的可变参考单元 通过 'ref' 和 '!'。

尝试将“donefiles”转换为引用,但似乎无法获得正确的语法。首先尝试了显而易见的(对我来说):

let donefiles : Set<FileRecord> = ref Set.empty

但:

错误 40 此表达式应具有类型 设置但这里有类型 'a ref

在这种情况下,我应该使用什么语法?

参考 f# 可变

评论

5赞 Lee 4/27/2017
您可以使用可变集来代替对不可变集合的可变引用?HashSet<FileRecord>
0赞 user1443098 4/27/2017
HashSet 似乎没有差分函数。
2赞 Lee 4/27/2017
可用于从 中删除项的集合。.ExceptWithHashSet<T>

答:

4赞 Fyodor Soikin 4/27/2017 #1

首先,您似乎使用的是旧版本的 F#。F# 4.0 中取消了对可变变量的限制。

但是,如果您无法切换到较新的版本,以下是实际问题的答案:

该函数接受一个值并返回一个可变单元格。此类单元格的类型为 ,其中 是值的类型。ref'a ref'a

因此,在您的情况下,函数返回 ,但您专门注释为 type ,因此存在冲突(这是编译器告诉您的)。refSet<FileRecord> refdonefilesSet<FileRecord>

只需调整您的类型注释,它就会起作用:

let donefiles : Set<FileRecord> ref = ref Set.empty

要更改 ref 单元格,请使用运算符::=

donefiles := Set.add file !donefiles

评论

0赞 user1443098 4/27/2017
它几乎奏效了!通过您的更改(谢谢!)变量声明有效,但闭包定义无效:我收到错误“值不可变”。我试过了。然后我尝试了“!donefiles <- Set.add file donefiles”并得到“分配左侧的无效表达式”。donefiles <- Set.add file donefiles
0赞 user1443098 4/27/2017
donefiles := Set.add file !donefiles工作(不得不去掉 var)