Reputation: 12137
I found this code online:
let tripleWise (source: seq<_>) =
seq {
use e = source.GetEnumerator()
if e.MoveNext() then
let i = ref e.Current
if e.MoveNext() then
let j = ref e.Current
while e.MoveNext() do
let k = e.Current
yield (!i, !j, k)
i := !j
j := k
}
it's similar to pairwise, but makes triplets.
I am curious as to why the author takes a reference on these lines:
let i = ref e.Current
let j = ref e.Current
instead of copying the value, while he copies the value directly in the loop.
Upvotes: 1
Views: 79
Reputation: 17153
I think the direct answer to your question is that i
and j
need to be mutable, whereas k
does not. (The original code was probably written back when reference cells were the standard way to mutate data in F#, rather than the mutable
keyword.) Had the author simply taken a copy, those variables wouldn't be mutable.
Upvotes: 1
Reputation: 2036
The author used as his starting point the implementation of Seq.pairwise. The current code for pairwise looks like this:
let pairwise (source: seq<'T>) =
checkNonNull "source" source
seq { use ie = source.GetEnumerator()
if ie.MoveNext() then
let mutable iref = ie.Current
while ie.MoveNext() do
let j = ie.Current
yield (iref, j)
iref <- j }
The mutable variable is rather strangely named iref. Sure enough, in an earlier version it was a ref cell. Lots of these were replaced with mutable variables in this commit:
https://github.com/dotnet/fsharp/pull/8063
This was mainly done for readability.
Clearly the author had based his code on the earlier version of Seq.pairwise.
Upvotes: 2