我遇到麻烦了。
我想创建一个函数,每次调用它时都会递增我的计数器,并用计数器号连接我的vargen字符串并返回这个新字符串。
我没有成功的是:
let (counter : int ref) = ref 0;;
let (vargen : string) = "_t";;
let tmp = incr counter;ref (vargen ^ string_of_int !counter);;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;
Printf.printf "%s\n" !tmp;;
但我的输出总是:
_t1
_t1
_t1
_t1
我的输出应该是什么:
_t0
_t1
_t2
_t3
任何解决我的问题的想法都是什么?
所有人。
答案 0 :(得分:8)
当您编写let tmp = ref foo
时,表达式foo
将被计算一次,以生成存储在引用中的值。访问引用将返回此值,而不重新评估原始表达式。
激发重新评估的方法是使用函数:如果你编写函数(fun () -> foo)
,这是一个值:它按原样返回,传递给函数,存储在引用中。每次将参数应用于此值时,都会计算表达式foo
。
Clément的解决方案很好。
的想法let counter =
let count = ref (-1) in
fun () -> incr count; !count
引用是否被分配一次,但每次调用函数fun () -> incr count; !count
时都会递增。使函数的局部参考避免了全局变量的一些缺陷。您可以将其视为函数counter
的“静态变量”,只是它是OCaml范围和评估规则的自然结果,而不是额外的,特定于函数的概念。
你甚至可以编写一个更通用的vargen
生成器,每次调用它时都会创建新的独立计数器:
let make_vargen prefix =
let count = ref (-1) in
fun () ->
incr count;
prefix ^ string_of_int !count
let fresh_t = make_vargen "t"
let () = print_endline (fresh_t ()) (* t0 *)
let () = print_endline (fresh_t ()) (* t1 *)
let fresh_u = make_vargen "u"
let () = print_endline (fresh_u ()) (* u0 *)
let () = print_endline (fresh_t ()) (* t2 *)
let () = print_endline (fresh_u ()) (* u1 *)
答案 1 :(得分:3)
由于tmp
是一个值,因此执行一次。将其更改为函数应该在每次调用tmp
时使计数器增加。
此外,为简单起见,您可以返回string
而不是string ref
:
let counter: int ref = ref (-1);;
let vargen: string = "_t";;
// tmp now is a function
let tmp() = incr counter; vargen ^ string_of_int !counter;;
Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
Printf.printf "%s\n" (tmp());;
答案 2 :(得分:3)
您可以使用
let tmp =
let counter = ref 0 in
(fun () -> incr counter; vargen ^ (string_of_int !counter))
使用tmp ()
调用函数,如果希望计数器从0开始,则将0更改为-1。
答案 3 :(得分:1)
如果您需要在不递增计数器的情况下可选地读取计数器,则可以添加参数:
let counter =
let count = ref (-1) in
fun do_incr -> if do_incr then begin incr count end; !count;;
使用它像:
# counter true;;
- : int = 0
# counter true;;
- : int = 1
# counter true;;
- : int = 2
# counter false;;
- : int = 2
# counter false;;
- : int = 2
# counter true;;
- : int = 3