caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Wish: mutable variant types, equivalence with records
@ 2012-03-24 18:26 Goswin von Brederlow
  2012-03-24 18:32 ` Lukasz Stafiniak
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Goswin von Brederlow @ 2012-03-24 18:26 UTC (permalink / raw)
  To: caml-list

Hi,

consider the code below that counts how often a value is printed.

The reason why this code works is that the memory layout of a
variant with arguments is identical to a record with the same
types. The only difference is that a variant sets the tag of the memory
block to reflect which constructor it is (here Bar = 0, Baz = 1).

But the code is fragile. It requires the use of Obj.magic and duplicates
the definitions of bar and baz (once as variant and once as record). If
the type of foo is changed but not the records then bad things will
happen.

There are ways to do this without Obj.magic:

type foo = Bar of bar_record | Baz of baz_record
type foo = Bar of int * int ref | Baz of float * int ref

The first adds an indirection for every access to foo and breaks
matching. The second adds an indirection for every mutable value in the
type. In both cases the extra indirections increase the memory footprint
and runtime.


So why not allow mutable in variant types and some equivalence with
records? For example:

type <name> = <Constructor> of [mutable] <type>[:label] [| ...]

as in:

type foo =
  | Bar of int:i * mutable int:bar_used
  | Baz of float:f * mutable int:baz_used

let use x =
  match x with
    | Bar bar ->
        bar.bar_used <- bar.bar_used + 1
    | Baz baz ->
        baz.baz_used <- baz.baz_used + 1

let print x =
  use x;
  match x with
  | Bar bar -> Printf.printf "%d\n" bar.i
  | Baz baz -> Printf.printf "%f\n" baz.f

The label is optional and any types in the constructor without label
would be translated into anonymous fields in a record that are
ineaccessible.

  type foo = Foo of int * mutable int:used

would be equivalent to { _ : int; mutable used : int; }

Taking it one step wurther one could even allow:

let bar = { i = 1; bar_used = 0; }
let foo = Bar bar
let foo = let Bar bar = foo in Bar { bar with i = 2; }


What do you think?

MfG
        Goswin

======================================================================
module Foo : sig
  type foo
  val make_bar : int -> foo
  val make_baz : float -> foo
  val get_used : foo -> int
  val print : foo -> unit
end = struct
  type foo = Bar of int * int | Baz of float * int
  type bar_record = { i : int; mutable bar_used : int; }
  type baz_record = { f : float; mutable baz_used : int; }

  let make_bar i = Bar (i, 0)
  let make_baz f = Baz (f, 0)

  let use x =
    match x with
    | Bar _ ->
        let (bar : bar_record) = Obj.magic x
        in bar.bar_used <- bar.bar_used + 1
    | Baz _ ->
        let (baz : baz_record) = Obj.magic x
        in baz.baz_used <- baz.baz_used + 1

  let get_used = function Bar (_, used) | Baz (_, used) -> used

  let print x =
    use x;
    match x with
    | Bar (i, _) -> Printf.printf "%d\n" i
    | Baz (f, _) -> Printf.printf "%f\n" f
end;;

let foo = Foo.make_bar 1
let used_before = Foo.get_used foo
let () = Foo.print foo
let used_after = Foo.get_used foo




^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-03-31 19:17 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-03-24 18:26 [Caml-list] Wish: mutable variant types, equivalence with records Goswin von Brederlow
2012-03-24 18:32 ` Lukasz Stafiniak
2012-03-24 18:39   ` Lukasz Stafiniak
2012-03-24 18:42     ` Lukasz Stafiniak
2012-03-25 22:45       ` Goswin von Brederlow
2012-03-24 18:42 ` Jonathan Protzenko
2012-03-24 18:45 ` Wojciech Meyer
2012-03-24 18:59   ` Lukasz Stafiniak
2012-03-29 22:46   ` François Bobot
2012-03-30 12:16     ` Goswin von Brederlow
2012-03-30 15:00       ` François Bobot
2012-03-31 15:52         ` Goswin von Brederlow
2012-03-31 19:17     ` Alain Frisch
2012-03-26  8:41 ` Romain Bardou

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).