是否有可能保证记忆的一致性?

时间:2016-04-09 05:10:43

标签: ocaml lazy-evaluation memoization mutable side-effects

我想用memoization构建一个模块Integer id = hibSession.save(record); Record createdRecord = hibSession.get(Record.class,id); return createdRecord 。类型I包含真实的复杂内容I.t和一些可变属性(例如c)。该模块为外部提供了计算和获取属性的函数(例如mutable is_cool),这可能代价高昂,这就是使用可变属性的原因:

is_cool

我所关注的是如何编写模块(*in i.ml *) module Content = struct type t = { i: int; mutable j: int } let is_cool (x: t) : bool = ... end module I : sig type t val get_c: t -> Content.t val is_cool: t -> bool ... end = struct type t = { c : Content.t; mutable is_cool : bool option; mutable property_a : int option } let get_c (x: t) -> Content.t = x.c let is_cool (x: t) : bool = match x.is_cool with | Some r -> r | None -> (* not yet calculated *) let r = Content.is_cool x.c in x.is_cool <- Some r; r end ... 和外部代码,以便在整个程序执行期间对于任何类型I的值,其可变属性始终与其内容一致I.t。一致意味着“可变属性应为cNone,其中Some v表示内容的当前属性。”

例如,模块v的签名禁止以下代码直接修改属性:

I.t

但是,似乎要禁止更改内容的代码并不容易:

(* in main.ml *)
open I

let test (x: I.t) = 
  x.is_cool <- Some false

改善此问题的一种方法是在模块(* in main.ml *) let test (x: I.t) (i_new: int) = let c = I.get_c x in let c_new = { c with Content.i = i_new } in let y = { x with c = c_new } in (* now the content and the properties in y are likely to be inconsistent *) 中添加set,并始终在I处使用set x c_new

{ x with c = c_new }

然而,仍有问题,例如,

1)仍然无法禁止人们撰写(*in i.ml *) let set (x: t) (c: Content.t) : t = { c = c; is_cool = None; property_a = None }

2)对{ x with c = c_new }中可变组件的修改(例如,Content.t)也会使mutable j: int不一致:

I.t

有没有人知道任何现有的反思或解决方案面临因记忆造成的这种不一致?如果我们总是在“record with”的地方使用(* in main.ml *) let test (x: I.t) (j_new: int) = let c = I.get_c x in c.Content.j <- j_new; (* now the content and the properties in x are likely to be inconsistent *) ,并且不允许set中的可变组件,我们能否保证100%的任何代码方案的一致性?

1 个答案:

答案 0 :(得分:0)

好吧,你可以使用私人

您的代码如下所示:

module type C = sig
  type t = private { i: int; mutable j: int }
  val new_c : int -> int -> t
  val is_cool : t -> bool
end
module Content : C = struct
  type t = { i: int; mutable j: int }
  let new_c = ...
  let is_cool (x: t) : bool = ...
end

module I : sig
  type t
  val new_i : int -> int -> t
  val get_c: t -> Content.t
  val is_cool: t -> bool
  ...
end = struct 
  type t = {
     c : Content.t; 
     mutable is_cool : bool option;
     mutable property_a : int option }

  let new_i = ...

  let get_c (x: t) -> Content.t = x.c

  let is_cool (x: t) : bool = 
    match x.is_cool with
    | Some r -> r
    | None -> (* not yet calculated *)
       let r = Content.is_cool x.c in
       x.is_cool <- Some r;
       r
  end
  ...

如果你试着写:

 let c = {i = 3; j = 3};;

它会拒绝你回答:

 Error: Cannot create values of the private type Content.t