2017-04-27 36 views
1

处理需要可变集的程序。当试图把集闭包我得到一个错误:F#从可变更改为参考

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

Error 40 The mutable variable 'donefiles' is used in an invalid way. Mutable variables cannot be captured by closures. Consider eliminating this use of mutation or using a heap-allocated mutable reference cell via 'ref' and '!'.

试图“donefiles”转换为参考,但似乎无法得到正确的语法。尝试了明显的(对我)第一次:

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

但:

Error 40 This expression was expected to have type Set but here has type 'a ref

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

+5

取而代之的是可变引用的一个不可改变的集合,你可以使用一个可变的'HashSet '? – Lee

+0

看来HashSet没有差异函数。 – user1443098

+2

您可以使用'.ExceptWith'从'HashSet '中移除一组物品。 – Lee

回答

4

首先,似乎你使用的是旧版本的F#。限制可变变量was lifted in F# 4.0

但如果你不能切换到新的版本,这里的答案的实际问题:

功能ref需要一个值,并返回一个可变的细胞。这种单元格的类型是'a ref,其中'a是值的类型。

所以你的情况,该ref函数返回Set<FileRecord> ref,但你特别注释donefiles有型Set<FileRecord>,所以有冲突(这是编译器告诉你)。

简单地调整你的类型的注释,它会工作:

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

变异一个引用单元格,使用:=操作:

donefiles := Set.add file !donefiles 
+0

它几乎奏效!随着你的改变(谢谢!)变量声明工作,但闭包定义没有:我得到错误“值不可变”。我试过'donefiles < - Set.add文件donefiles'。然后我尝试了'!donefiles < - Set.add文件donefiles'并得到了“赋值左边的无效表达式”。 – user1443098

+0

我已经更新了答案。 –

+0

'donefiles:= Set.add文件!donefiles'工作(不得不取消var) – user1443098