From: Goswin von Brederlow <goswin-v-b@web.de>
To: caml-list@inria.fr
Subject: [Caml-list] Wish: mutable variant types, equivalence with records
Date: Sat, 24 Mar 2012 19:26:37 +0100 [thread overview]
Message-ID: <87fwcx6ejm.fsf@frosties.localnet> (raw)
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
next reply other threads:[~2012-03-24 18:26 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-24 18:26 Goswin von Brederlow [this message]
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
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=87fwcx6ejm.fsf@frosties.localnet \
--to=goswin-v-b@web.de \
--cc=caml-list@inria.fr \
/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).