caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Alain Frisch <alain@frisch.fr>
To: Martin Jambon <martin.jambon@ens-lyon.org>,
	 Anthony Tavener <anthony.tavener@gmail.com>
Cc: "caml-list@inria.fr" <caml-list@inria.fr>
Subject: Re: [Caml-list] Heterogeneous dictionary
Date: Thu, 04 Apr 2013 09:32:51 +0200	[thread overview]
Message-ID: <515D2CA3.2070709@frisch.fr> (raw)
In-Reply-To: <515D1B65.3070603@ens-lyon.org>

On 04/04/2013 08:19 AM, Martin Jambon wrote:
> type 'a t = ('a, (unit -> unit)) Hashtbl.t
>
> let create n = Hashtbl.create n
>
> let access () =
>    let r = ref None in
>    let get tbl k =
>      try
>        (Hashtbl.find tbl k) ();
>        let result = !r in
>        r := None;
>        result
>      with Not_found -> None
>    in
>    let set tbl k v =
>      let v_opt = Some v in
>      Hashtbl.replace tbl k (fun () -> r := v_opt)
>    in
>    get, set

Careful, this is buggy!  If you apply the "get" on an existing value 
with the "wrong" type, it will set the slot corresponding to that wrong 
type, which can result in a fake "get" later on that type.

# let h = create 10;;
val h : '_a X.t = <abstr>
# let (get1, set1) = access ();;
val get1 : '_a X.t -> '_a -> '_b option = <fun>
val set1 : '_a X.t -> '_a -> '_b -> unit = <fun>
# let (get2, set2) = access ();;
val get2 : '_a X.t -> '_a -> '_b option = <fun>
val set2 : '_a X.t -> '_a -> '_b -> unit = <fun>
# set1 h "a" true;;
- : unit = ()
# set2 h "b" "X";;
- : unit = ()
# get1 h "b";;
- : bool option = None
(*  ====> the slot for get2/set2 has been filled! *)

# get2 h "a";;
- : string option = Some "X"

(* WRONG! *)


Here is an implementation of the same interface based on local 
exceptions.  It avoids the bug above and it is also more efficient and 
thread-safe:


type 'a t = ('a, exn) Hashtbl.t

let create n = Hashtbl.create n

let access (type t) () =
   let module M = struct exception E of t end in
   let r = ref None in
   let get tbl k =
     try
       match Hashtbl.find tbl k with
       | M.E x -> Some x
       | _ -> None
     with Not_found -> None
   in
   let set tbl k v =
     Hashtbl.replace tbl k (M.E v)
   in
   get, set

(If [get] is more frequent than [set], it is worth storing a "t option" 
in the exception directly.)

-- Alain

  reply	other threads:[~2013-04-04  7:32 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-04-04  0:45 Anthony Tavener
2013-04-04  1:29 ` Yaron Minsky
2013-04-04  2:18   ` Anthony Tavener
2013-04-04  6:19 ` Martin Jambon
2013-04-04  7:32   ` Alain Frisch [this message]
2013-04-04 18:16     ` Martin Jambon
2013-04-04  7:38 ` Raphaël Proust
2013-04-04  8:37   ` Anthony Tavener
2013-04-04  9:04     ` David House
2013-04-04 18:48       ` Anthony Tavener
2013-04-05 16:37         ` Yaron Minsky
2013-04-05 18:27           ` Anthony Tavener
2013-04-05 18:51             ` Yaron Minsky
2013-04-05 19:55               ` Anthony Tavener
2013-04-05 20:03                 ` Yaron Minsky
2013-04-05 20:27                   ` Anthony Tavener
2013-04-08  8:33                     ` David House

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=515D2CA3.2070709@frisch.fr \
    --to=alain@frisch.fr \
    --cc=anthony.tavener@gmail.com \
    --cc=caml-list@inria.fr \
    --cc=martin.jambon@ens-lyon.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).