代码之家  ›  专栏  ›  技术社区  ›  Snark

记忆尾调用优化了f[重复]中的递归函数

  •  1
  • Snark  · 技术社区  · 14 年前

    可能重复:
    Combine memoization and tail-recursion

    下面是我编写的代码,尾调用使用累积变量进行了优化

    let rec counter init count = 
        if init = 1 then count + 1 else
        match init with
        | Even value -> (counter (value/2)  (1 + count))
        | Odd value -> (counter ((3 * value) + 1) (count+1))
    
    let SeqBuilder (initval:int) : int =
        counter initval 0
    

    我该怎么回忆?我在尝试记忆时遇到的问题是递归调用必须转到memoize对象,所以您必须有一个…递归对象?

    还是简单多了,我只是没有经验?

    1 回复  |  直到 12 年前
        1
  •  3
  •   Tomas Petricek    14 年前

    f允许您定义 递归值 (就像你提到的递归对象),所以如果你有 memoize2 函数执行memoization(采用两个参数的函数-使其与 counter ,然后你可以写:

    let rec counter = memoize2 (fun init count ->
      if init = 1 then count + 1 else 
      match init with 
      | Even value -> (counter (value/2) (1 + count)) 
      | Odd value -> (counter ((3 * value) + 1) (count+1)) )
    

    像这样的递归引用可能很危险,因此f插入一些运行时检查。它也会给出警告 FS0040 要通知您这一点,但是在这种情况下,递归是正确的(如果在初始化期间访问了递归引用,可能会出现问题-这里我们只在稍后使用它,当函数已经声明时,所以一切都很好)。您可以通过添加 #nowarn "40" .