6

因此,如果您去银行,有一个设备可以从中提取号码。

我想写一个这样的函数。所以每次调用这个函数时,我们都会得到系列中的下一个数字。

所以如果这个函数第一次被调用,我们得到 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...

4

3 回答 3

9

你必须返回一个函数。而对于它,你每次都必须通过一些东西,即你的+1必须被推迟。

let factory = 
    let counter = ref 0
    fun () -> 
        counter.Value <- !counter + 1
        !counter

现在你得到

> factory();;
val it : int = 1
> factory();;
val it : int = 2

这样做有一个很好的副作用,即您将可变参考单元完全隐藏在函数内,因此无法以某种方式篡改您的计数器。

于 2013-08-11T06:54:52.573 回答
8

仅供参考,如果您想要一个使用序列的版本(就像您问题中的第一种方法一样),您可以使用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

它的行为与factory丹尼尔的回答相同。这仍然使用可变状态 - 但它隐藏在枚举器中(它保持MoveNext调用之间序列的当前状态)。

在这个简单的例子中,我会使用 Daniel 的版本,但如果你想迭代其他东西而不仅仅是增加数字,上面的方法可能会很方便。

于 2013-08-11T07:33:20.557 回答
6

您需要将变量移到声明之外。您还需要声明一个函数,以便在每次调用时对其进行评估。

let mutable i = 1
let X() =
    i <- i + 1
    i

这样可以确保每次调用该函数并且变量正确递增。

于 2013-08-11T05:13:42.443 回答