Version française
Home     About     Download     Resources     Contact us    
Browse thread
Weak hash table for attaching extra data to an object
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Jon Harrop <jon@f...>
Subject: Re: [Caml-list] Weak hash table for attaching extra data to an object
On Tuesday 14 August 2007 12:08:11 Thomas Fischbacher wrote:
> Richard Jones wrote:
> > I have a module which I can't edit[1].  This module, let's call it
> > Document, stores a representation of an XML tree in internal node
> > objects:
> >
> >   type intnode
> >
> > What I want to do is -- completely outside Document -- attach my own
> > extra information to these nodes.
>
> Ah, so the situation really is somewhat common, and not something
> just I am running into occasionally. (The problem in particular
> also arises occasionally when writing symbolic algebra code when one
> wants to attach meta-data (e.g. on typesetting) to terms without
> touching the underlying term representations in any way.)

I think this is an important design choice that people should be aware of when 
they first write the code. If you think the product types inside your expr 
type will be extended:

  type expr =
    | Int of int
    | Var of string
    | Seq of expr * expr array;;

with pattern matches like this:

  Seq(h, t) -> ...

Then a good first step is to turn n-ary constructor arguments into a single 
record:

  type expr =
    | Int of int
    | Var of string
    | Seq of seq
  and seq = {h: expr; t: expr array};;

Then you write your pattern matches like this:

  Seq{h=h; t=t} -> ...

and you are free to add more fields to the record without having to update 
such pattern matches. You also need to replace direct construction with an 
explicit constructor function:

  let seq h t = Seq{h=h; t=t}

You can also parameterize the type over metadata:

  type 'a expr =
    | Int of int
    | Var of string
    | Seq of 'a seq
  and 'a seq = {h: 'a expr; t: 'a expr array; meta: 'a};;

Now you can insert arbitrary metadata into Seq nodes.

Another possible solution (at design time) is to "untie the recursive knot" of 
the data structure:

  type 'expr aexpr =
    | Int of int
    | Var of string
    | Seq of 'expr * 'expr array;;

This allows you to bind data structures together and, in particular, lets you 
inject metadata nodes between levels of exprs in the tree:

  type 'a expr = Meta of 'a * 'a expr aexpr;;

(This can be done more efficiently using -rectypes)

If your metadata are heavily used (e.g. hashing or culling information) and 
you are designing your own data structure then these approaches can all be 
useful (as well as polymorphic variants, that allow other forms of extension) 
because these approaches all result in fast code.

If your metadata are sporadically used or, in particular, only sparsely 
present or you do not have access to the library then the weak hash table 
approach is probably the way to go.

-- 
Dr Jon D Harrop, Flying Frog Consultancy Ltd.
OCaml for Scientists
http://www.ffconsultancy.com/products/ocaml_for_scientists/?e