在F#中记忆尾调用优化的递归函数

时间:2010-09-17 22:03:52

标签: f# memoization

  

可能重复:
  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 个答案:

答案 0 :(得分:3)

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"来停用警告。