Reputation: 7685
Working on a program that needs a mutable set. When trying to put the set in a closure I get an error:
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 '!'.
Trying to convert "donefiles" into a ref, but can't seem to get the syntax right. Tried the obvious (to me) first:
let donefiles : Set<FileRecord> = ref Set.empty
but:
Error 40 This expression was expected to have type Set but here has type 'a ref
What is the syntax I should use in this case?
Upvotes: 1
Views: 315
Reputation: 80915
First of all, it seems that you're using an older version of F#. This limitation on mutable variables was lifted in F# 4.0.
But in case you can't switch to a newer version, here's the answer to the actual question:
The function ref
takes a value and returns a mutable cell. The type of such cell is 'a ref
, where 'a
is the type of the value.
So in your case, the ref
function returns Set<FileRecord> ref
, but you specifically annotated donefiles
to have type Set<FileRecord>
, so there's a conflict (this is what the compiler is telling you).
Simply adjust your type annotation, it will work:
let donefiles : Set<FileRecord> ref = ref Set.empty
To mutate a ref cell, use the :=
operator:
donefiles := Set.add file !donefiles
Upvotes: 4