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