为OCaml中的递归函数定义静态变量

时间:2011-12-28 18:50:50

标签: variables recursion ocaml

我有一个递归函数fact,可以从其中的表达式或其外部的表达式调用。

我想将fact与变量v相关联,以便每次从外部(另一个函数)调用fact时,{{1 }}已初始化,其值可在v内更改,但从内部调用fact时永远无法初始化。

以下代码符合我的需要,但有一个问题是fact被定义为全局变量,我必须在从外部调用v之前执行v := init,我这样做找不到美丽。

fact

有人能想到更好的实施吗?

3 个答案:

答案 0 :(得分:5)

您可以隐藏包含函数体内的函数和值定义,如下所示:

open Printf

let init = 100

let fact n =
  let rec fact counter n =
    incr counter;
    if n <= 0 then 1 else n * fact counter (n - 1)
  in
  let counter = ref init in
  let result = fact counter n in
  (result, !counter)

let main () =
  let x, count = fact 3 in
  printf "%i\n" x;
  printf "counter: %i\n" count (* 104 is expected *)

let () = main ()

答案 1 :(得分:3)

您可以调整Martin的解决方案,以便在各种调用之间共享数据:

let fact =
  let counter = ref 0 in
  fun n ->
    let rec fact = ... in     
    fact n

我们的想法是将let fact = fun n -> let counter = ... in ...转换为let fact = let counter = ... in fun n -> ...:计数器初始化一次,而不是每次调用fact

这种风格的典型例子是:

let counter =
  let count = ref (-1) in
  fun () ->
    incr count;
    !count

请注意,如果函数是多态的,你可能会遇到输入错误:let foo = fun n -> ...总是被推广到多态函数中,let foo = (let x = ref ... in fun n -> ...)不是,因为它不健全,所以{ {1}}不会有多态类型。

您甚至可以将上面的计数器示例概括为计数器工厂

foo

对于let make_counter () = let count = ref (-1) in fun () -> incr count; !count 的每次调用,您都会获得一个新计数器,这是一个在调用时共享状态的函数,但其​​状态独立于之前的make_counter ()计数器创建。

答案 2 :(得分:1)

使用Ocaml的对象,您可以:

class type fact_counter = object ('self)
  method get : int
  method set : int -> unit
  method inc : unit
  method fact : int -> int
end;;

class myCounter init : fact_counter = object (self)
  val mutable count = init
  method get = count
  method set n = count <- n
  method inc = count <- count + 1
  method fact n =
    self#inc;
    if n <= 0 then 1 else n * self#fact (n - 1)
end;;

然后你可以获得:

# let c = new myCounter 0;;
val c : myCounter = <obj>
# c#fact 10;;              
- : int = 3628800
# c#get;;                  
- : int = 11
# c#set 42;;               
- : unit = ()
# c#fact 10;;              
- : int = 3628800
# c#get;;    
- : int = 53

我希望您能轻松了解如何调整myCounter以包含fib ...