SML:跟踪迭代次数

SML: Keeping track of number of iterations

我确信有一种方法可以在 SML 中优雅地执行此操作,但我很难跟踪迭代次数(基本上是我的函数被调用的次数)。

我正在尝试编写一个计算结果为一对数字的函数,一个代表答案的底数,另一个代表余数。因此,如果您致电:

divmod(11, 2),你会得到 (5, 1)

这是我目前的情况:

divmod(number : int, divisor : int) =
    if number < divisor then
        (number, count)
    else
        divmod(number - divisor, divisor);

显然,我没有设置我的计数变量,所以它不会编译,但这就是算法的想法。剩下的就是将 count 初始化为 0 并能够在递归调用之间传递它。但是我只允许这个函数的两个参数。

不过,我可以编写辅助函数。

想法?

如果 SML 支持嵌套函数,您可以这样做:

divmod(number : int, divisor : int) =
   _divmod(n : int, d : int, count : int) = 
      if n < d then
         (count, n)
      else
         _divmod(n - d, d, count + 1)
   _divmod(number, divisor, 0)

就个人而言,我 喜欢 SML 不是纯函数式语言这一事实​​。跟踪函数调用自然是通过副作用完成的(而不是显式传递计数器变量)。

例如,给定一个通用的递归斐波那契数列:

fun fib 0 = 0
|   fib 1 = 0
|   fib n = fib(n-2) + fib(n-1);

您可以修改它,以便每次调用它时都会增加一个计数器作为副作用:

counter = ref 0;

fun fib 0 = (counter := !counter + 1; 0)
|   fib 1 = (counter := !counter + 1; 1)
|   fib n = (counter := !counter + 1; fib(n-2) + fib(n-1));

您可以直接使用它,也可以稍微包装一下:

fun fibonacci n = (
    counter :=0; 
    let val v = fib n 
    in 
        (!counter,v) 
    end);

典型的运行:

- fibonacci 30;
val it = (2692537,832040) : int * int  

(顺便说一下,这说明了为什么这个版本的斐波那契递归不是很好!)