【问题标题】:SML: Keeping track of number of iterationsSML:跟踪迭代次数
【发布时间】:2015-08-16 03:56:20
【问题描述】:

我确信有一种方法可以在 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 是否允许嵌套函数?在这种情况下,您可以使用它来传递 count 参数。

标签: functional-programming sml


【解决方案1】:

如果 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)

【讨论】:

  • 我想我可以开玩笑地在 divmod 外部定义该函数,然后在 divmod 中调用它,不是吗?另外,你的最后一行是做什么的?
  • 是的,如果您愿意,您可以在divmod 之外定义_divmod,并从后者调用前者。最后一行使用从外部函数传递的值加上 count 的初始值(为零)调用嵌套函数。
【解决方案2】:

就个人而言,我喜欢 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  

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-23
    • 2016-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-19
    • 2021-05-26
    • 1970-01-01
    相关资源
    最近更新 更多