为什么在这种情况下使用引用,在 F# 中
Why use references in this scenario, in F#
我在网上找到这段代码:
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
}
它类似于成对的,但会生成三胞胎。
我很好奇作者为什么引用这些行:
let i = ref e.Current
let j = ref e.Current
而不是复制值,而他直接在循环中复制值。
作者使用 Seq.pairwise 的实现作为他的出发点。 pairwise 的当前代码如下所示:
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 }
可变变量的名字很奇怪 iref。果然,在早期版本中它是一个 ref cell。在此提交中,其中很多被替换为可变变量:
https://github.com/dotnet/fsharp/pull/8063
这样做主要是为了便于阅读。
很明显,作者的代码是基于 Seq.pairwise 的早期版本。
我认为您问题的直接答案是 i
和 j
需要可变,而 k
不需要。 (当引用单元格是 F# 中改变数据的标准方法而不是 mutable
关键字时,原始代码可能被写回了。)如果作者只是复制一份,这些变量将不会可变。
我在网上找到这段代码:
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
}
它类似于成对的,但会生成三胞胎。
我很好奇作者为什么引用这些行:
let i = ref e.Current
let j = ref e.Current
而不是复制值,而他直接在循环中复制值。
作者使用 Seq.pairwise 的实现作为他的出发点。 pairwise 的当前代码如下所示:
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 }
可变变量的名字很奇怪 iref。果然,在早期版本中它是一个 ref cell。在此提交中,其中很多被替换为可变变量:
https://github.com/dotnet/fsharp/pull/8063
这样做主要是为了便于阅读。
很明显,作者的代码是基于 Seq.pairwise 的早期版本。
我认为您问题的直接答案是 i
和 j
需要可变,而 k
不需要。 (当引用单元格是 F# 中改变数据的标准方法而不是 mutable
关键字时,原始代码可能被写回了。)如果作者只是复制一份,这些变量将不会可变。