OCaml:两个函数的内部 "let"
OCaml: inner "let" for two functions
我想制作内部 "let",但有两个功能。
我现在有一个功能
let fresh_var () =
let r = ref 0 in
r := !r + 1 ; Var !r;;
我想添加第二个函数,以便它可以更改 r,但 r 在程序的其余部分保持不可见。类似于:
let r = ref 0 in
let fresh_var () = r := !r + 1 ; Var !r
and let refresh () = r := 0
但是由于语法错误,上面的部分不起作用。
如何在 OCaml 中实现这个想法?
and
是用来代替let
的,当你要写联合声明的时候,in
只在局部上下文中使用:
let r = ref 0
let fresh_var () = r := !r + 1 ; Var !r
and refresh () = r := 0
但是,由于您的函数不是相互依赖的,因此此处不需要使用 and
,因此您可以使用另一个 let
结构。
至于你的想法,你必须在一个单独的模块中定义这些函数,该模块的 .mli
只声明它们而不是变量 r
.
这不是 OCaml 中的工作方式。 本地 定义正是本地的。它们不能在函数之间共享。
如果您想抽象部分实现,我建议改用模块。
module Incrementer : sig
val next : unit -> int
val reset : unit -> unit
end = struct
let r = ref 0
let next () =
r := !r + 1;
!r
let reset () =
r := 0
end
查看下面的实际操作:
# Incrementer.next ();;
- : int = 1
# Incrementer.next ();;
- : int = 2
# Incrementer.reset ();;
- : unit = ()
# Incrementer.next ();;
- : int = 1
# Incrementer.r;;
Error: Unbound value Incrementer.r
下面是一个更好的实现,它允许您一次拥有多个 Incrementers
。
module Incrementer : sig
type t
val create : unit -> t
val next : t -> int
val reset : t -> unit
end = struct
type t = int ref
let create () =
ref 0
let next t =
t := !t + 1;
!t
let reset t =
t := 0
end
让我们看看实际效果:
# let incrementer = Incrementer.create ();;
val incrementer : Incrementer.t = <abstr>
(* As you can see, the outer code never sees the `int ref` inside. *)
# Incrementer.next incrementer;;
- : int = 1
# Incrementer.next incrementer;;
- : int = 2
# Incrementer.reset incrementer;;
- : unit = ()
# Incrementer.next incrementer;;
- : int = 1
您也可以将签名和实现写在单独的文件中,以便单独编译它们。
您可以简单地创建一个返回一对函数的函数:
let get_fresh_and_reset () =
let r = ref 0 in
(fun () -> incr r; !r), (fun () -> r := 0)
let fresh, reset = get_fresh_and_reset ()
另请注意,正确的语法是 :=
而不是 =:
。
编辑:
如@Virgile所述,如果您不需要多个计数器,您可以简化:
let fresh_var, refresh =
let r = ref 0 in (fun () -> incr r; !r), (fun () -> r:=0)
OCaml 还支持丰富的面向对象系统
class counter = object
val mutable r = 0
method value =
r
method incr =
r <- r + 1;
r
method reset =
r <- 0;
0
end
我们可以这样使用我们的counter
let () =
let c = new counter in
printf "counter value: %d\n" c#value; (* counter value: 0 *)
printf "counter value: %d\n" c#incr; (* counter value: 1 *)
printf "counter value: %d\n" c#incr; (* counter value: 2 *)
printf "counter value: %d\n" c#incr; (* counter value: 3 *)
printf "counter value: %d\n" c#value; (* counter value: 3 *)
printf "counter value: %d\n" c#value; (* counter value: 3 *)
printf "counter value: %d\n" c#reset; (* counter value: 0 *)
printf "counter value: %d\n" c#incr; (* counter value: 1 *)
Class实例封装了自己的数据成员,方便我们管理多个计数器
let () =
let a = new counter in
let b = new counter in
printf "A: %d, B: %d\n" a#value b#value; (* A: 0, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 1, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 2, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 3, B: 0 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 1 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 2 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 3 *)
printf "A: %d, B: %d\n" a#reset b#reset; (* A: 0, B: 0 *)
我想制作内部 "let",但有两个功能。
我现在有一个功能
let fresh_var () =
let r = ref 0 in
r := !r + 1 ; Var !r;;
我想添加第二个函数,以便它可以更改 r,但 r 在程序的其余部分保持不可见。类似于:
let r = ref 0 in
let fresh_var () = r := !r + 1 ; Var !r
and let refresh () = r := 0
但是由于语法错误,上面的部分不起作用。
如何在 OCaml 中实现这个想法?
and
是用来代替let
的,当你要写联合声明的时候,in
只在局部上下文中使用:
let r = ref 0
let fresh_var () = r := !r + 1 ; Var !r
and refresh () = r := 0
但是,由于您的函数不是相互依赖的,因此此处不需要使用 and
,因此您可以使用另一个 let
结构。
至于你的想法,你必须在一个单独的模块中定义这些函数,该模块的 .mli
只声明它们而不是变量 r
.
这不是 OCaml 中的工作方式。 本地 定义正是本地的。它们不能在函数之间共享。
如果您想抽象部分实现,我建议改用模块。
module Incrementer : sig
val next : unit -> int
val reset : unit -> unit
end = struct
let r = ref 0
let next () =
r := !r + 1;
!r
let reset () =
r := 0
end
查看下面的实际操作:
# Incrementer.next ();;
- : int = 1
# Incrementer.next ();;
- : int = 2
# Incrementer.reset ();;
- : unit = ()
# Incrementer.next ();;
- : int = 1
# Incrementer.r;;
Error: Unbound value Incrementer.r
下面是一个更好的实现,它允许您一次拥有多个 Incrementers
。
module Incrementer : sig
type t
val create : unit -> t
val next : t -> int
val reset : t -> unit
end = struct
type t = int ref
let create () =
ref 0
let next t =
t := !t + 1;
!t
let reset t =
t := 0
end
让我们看看实际效果:
# let incrementer = Incrementer.create ();;
val incrementer : Incrementer.t = <abstr>
(* As you can see, the outer code never sees the `int ref` inside. *)
# Incrementer.next incrementer;;
- : int = 1
# Incrementer.next incrementer;;
- : int = 2
# Incrementer.reset incrementer;;
- : unit = ()
# Incrementer.next incrementer;;
- : int = 1
您也可以将签名和实现写在单独的文件中,以便单独编译它们。
您可以简单地创建一个返回一对函数的函数:
let get_fresh_and_reset () =
let r = ref 0 in
(fun () -> incr r; !r), (fun () -> r := 0)
let fresh, reset = get_fresh_and_reset ()
另请注意,正确的语法是 :=
而不是 =:
。
编辑:
如@Virgile所述,如果您不需要多个计数器,您可以简化:
let fresh_var, refresh =
let r = ref 0 in (fun () -> incr r; !r), (fun () -> r:=0)
OCaml 还支持丰富的面向对象系统
class counter = object
val mutable r = 0
method value =
r
method incr =
r <- r + 1;
r
method reset =
r <- 0;
0
end
我们可以这样使用我们的counter
let () =
let c = new counter in
printf "counter value: %d\n" c#value; (* counter value: 0 *)
printf "counter value: %d\n" c#incr; (* counter value: 1 *)
printf "counter value: %d\n" c#incr; (* counter value: 2 *)
printf "counter value: %d\n" c#incr; (* counter value: 3 *)
printf "counter value: %d\n" c#value; (* counter value: 3 *)
printf "counter value: %d\n" c#value; (* counter value: 3 *)
printf "counter value: %d\n" c#reset; (* counter value: 0 *)
printf "counter value: %d\n" c#incr; (* counter value: 1 *)
Class实例封装了自己的数据成员,方便我们管理多个计数器
let () =
let a = new counter in
let b = new counter in
printf "A: %d, B: %d\n" a#value b#value; (* A: 0, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 1, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 2, B: 0 *)
printf "A: %d, B: %d\n" a#incr b#value; (* A: 3, B: 0 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 1 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 2 *)
printf "A: %d, B: %d\n" a#value b#incr; (* A: 3, B: 3 *)
printf "A: %d, B: %d\n" a#reset b#reset; (* A: 0, B: 0 *)