user1443098
user1443098

Reputation: 7685

F# Changing from mutable to ref

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

Answers (1)

Fyodor Soikin
Fyodor Soikin

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

Related Questions