因此,如果你去银行有一个设备,你可以从中提取一个号码.
我想写一个这样的函数.因此,每次调用此函数时,我们都会在该系列中获得下一个数字.
因此,如果第一次调用此函数,我们得到1.第二次得到2 ....依此类推.
这是我到目前为止所写的内容
let X =
let myseq = seq {1 .. 100}
let GetValue =
Seq.head (Seq.take 1 myseq)
GetValue;;
let p = X;;
p;;
p;;
p;;
Run Code Online (Sandbox Code Playgroud)
但它总是返回1.我的希望是因为序列是一个闭包,每次我拿一个,我会得到下一个数字.
我也尝试过这个
let X =
let mutable i = 1
let GetValue =
i <- i + 1
i
GetValue;;
let p = X;;
p;;
p;;
p;;
Run Code Online (Sandbox Code Playgroud)
这只打印2 ...
你必须返回一个函数.而且,你必须每次都传递一些东西,即你+1必须推迟.
let factory =
let counter = ref 0
fun () ->
counter.Value <- !counter + 1
!counter
Run Code Online (Sandbox Code Playgroud)
现在你明白了
> factory();;
val it : int = 1
> factory();;
val it : int = 2
Run Code Online (Sandbox Code Playgroud)
这样做有很好的副作用,你完全隐藏了函数内部的可变参考单元格,因此没有办法以某种方式篡改你的计数器.
仅供参考,如果您想要一个使用序列的版本(就像您问题中的第一种方法一样),您可以使用该IEnumerable界面执行此操作:
let factory =
// Infinite sequence of numbers & get enumerator
let numbers = Seq.initInfinite id
let en = numbers.GetEnumerator()
fun () ->
// Move to the next number and return it
en.MoveNext() |> ignore
en.Current
Run Code Online (Sandbox Code Playgroud)
它的行为与factory丹尼尔的答案相同.这仍然使用可变状态 - 但它隐藏在枚举器内(它保持MoveNext调用之间序列的当前状态).
在这个简单的例子中,我会使用Daniel的版本,但如果你想迭代其他东西而不仅仅是增加数字,上面的内容可能很方便.
您需要在声明之外移动变量.您还需要声明一个函数,以便在每次调用时对其进行求值.
let mutable i = 1
let X() =
i <- i + 1
i
Run Code Online (Sandbox Code Playgroud)
这确保了每次调用函数并且变量正确递增.