This marvelous code by Marc Stiegler is a source of matched sealer-unsealer pairs in OCaml very much like those proposed by Morris in 1973.
let makeSealerPair nullObj =
    let content = ref nullObj in
    let seal obj =
       let box () = content := obj in
       box in
    let unseal filledbox =
       content := nullObj;
       filledbox ();
       let result = !content in
       content := nullObj;
       result in
    (seal, unseal)
;;
Here is a simple test—demo:
let seal, unseal = makeSealerPair "Zilch";;
unseal (seal "Hello");;

let s1, u1 = makeSealerPair 34;;
let s2, u2 = makeSealerPair 34;;
u1 (s2 11);; => 34
OCaml deduces that the type of makeSealerPair is:
'a → ('a → unit → unit) * ((unit → 'b) → 'a)

This nice code needs careful commentary. Each invocation of makeSealerPair returns a matched pair of functions called the sealer and unsealer. Invoking a sealer with argument zot yields a box with zot inside. Invoking the matched unsealer passing that box returns zot.

The identifier content sounds like it refers to zot. It does not except for a brief moment as the unsealer is invoked. This code is not thread safe. A given matched pair is good only for one type and that is the type of the argument to makeSealerPair—a kosher pair.

The code for unseal stores nullObj into the cell content twice for reasons that are slightly obscure.

There is an obscure ‘burden’ placed upon legitimate holders of these boxes. One must not invoke them lest certain attacks be enabled! How to express this?? It is not a burden on the code which gains no legitimate function by invoking a box. It places a burden on the programmer in understanding the warning.

This plan is incompatible with preemptive scheduling since there is one mutable cell, content which is shared by boxes from the same matched sealer unsealer pair. Platforms that survive time hogs must preempt, I presume. That enables attacks where threads of code that mutate may be interleaved.


Minor stylistic mods give:
let makeSealerPair nullObj = let content = ref nullObj in
  let seal obj = let box () = content := obj in box
  and unseal filledbox = content := nullObj; filledbox ();
    let result = !content in content := nullObj; result
in (seal, unseal);;
Slightly smaller and obscurer:
let makeSealerPair nullObj = let content = ref nullObj in
  let seal obj () = content := obj
  and unseal filledbox = content := nullObj; filledbox ();
     let result = !content in content := nullObj; result
in (seal, unseal);;
Worse:
let makeSealerPair nullObj = let content = ref nullObj in
  (fun obj () -> content := obj),
  (fun filledbox -> content := nullObj; filledbox ();
     let result = !content in content := nullObj; result);;

In Scheme.

Guttag Specs

Real soon now …

See this! I have always been queasy about weak maps but I can’t pin down any problems with them.

Clouds