我正在学习OCaml。我知道OCaml为我们提供了编程和函数式编程的强制性风格。OCaml中的记忆和参考列表
我碰到这个代码来为我的课程来计算OCaml中
let memoise f =
let table = ref []
in
let rec find tab n =
match tab with
| [] ->
let v = (f n)
in
table := (n, v) :: !table;
v
| (n', v) :: t ->
if n' = n then v else (find t n)
in
fun n -> find !table n
let fibonacci2 = memoise fibonacci1
凡功能fibonacci1
以标准方式实现的第n个Fibonacci数的部分内容如下:
let rec fibonacci1 n =
match n with
| 0 | 1 -> 1
| _ -> (fibonacci1 (n - 1)) + (fibonacci1 (n - 2))
现在我的问题是,我们如何实现fibonacci2中的memoisation。 table
已在函数fibonacci2中定义,因此,我的逻辑规定函数完成计算后,列表table
应该丢失,并且在每次调用之后,表将一次又一次地建立。
我跑了一些简单的测试,我在OCaml REPL中调用了函数fibonacci 35
两次,第二次函数调用的返回速度明显快于第一次调用该函数(与我的预期相反)。
我虽然这可能是可能的,如果声明变量使用ref
默认给它一个全局范围。
所以,我想这个
let f y = let x = ref 5 in y;;
print_int !x;;
但是,这给了我一个错误,指出x的值是无界的。
为什么这样表现?
你说这个返回的值'f'是一个函数,但你也可以说这个值的一部分就是这个表。我不确定这意味着什么。 –
函数与函数的所有自由变量(所有未在函数中定义的名称)的值捆绑在一个闭包中。所以,一个函数(或者一个闭包)实际上可以有任意的东西。 “memoise”返回的封闭内有表格。 –