1

可能的重复:
结合记忆和尾递归

所以下面是我写的代码,使用累积变量优化的尾调用

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

我如何记住这个?当我尝试记忆时遇到的问题是递归调用必须转到记忆对象,所以你必须有一个......递归对象?

还是它更简单,我只是缺乏经验?

4

1 回答 1

3

F# 允许你定义一个递归值(比如你提到的递归对象),所以如果你有memoize2函数来做记忆(采用两个参数的函数 - 使其与你的兼容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"

于 2010-09-18T03:24:35.150 回答