From mboxrd@z Thu Jan 1 00:00:00 1970 X-Sympa-To: caml-list@inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id q2Q8fFGC006831 for ; Mon, 26 Mar 2012 10:41:16 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AmQDANMqcE9XYrNCnGdsb2JhbABEtRiDOgEBAQEBCAsJCRQnggoBBScLAQVBEAshJQ8CRgYNAQcChg2BeQS4Q5EoBJtxjQWBWg X-IronPort-AV: E=Sophos;i="4.73,649,1325458800"; d="scan'208";a="137698811" Received: from 19.mo4.mail-out.ovh.net (HELO mo4.mail-out.ovh.net) ([87.98.179.66]) by mail4-smtp-sop.national.inria.fr with ESMTP; 26 Mar 2012 10:41:10 +0200 Received: from mail408.ha.ovh.net (b6.ovh.net [213.186.33.56]) by mo4.mail-out.ovh.net (Postfix) with SMTP id 2CB85104E7AA for ; Mon, 26 Mar 2012 10:41:22 +0200 (CEST) Received: from b0.ovh.net (HELO queueout) (213.186.33.50) by b0.ovh.net with SMTP; 26 Mar 2012 10:41:10 +0200 Received: from unknown (HELO ?138.231.81.152?) (romain%bardou.fr@138.231.81.152) by ns0.ovh.net with SMTP; 26 Mar 2012 10:41:09 +0200 Message-ID: <4F702B9C.30302@lsv.ens-cachan.fr> Date: Mon, 26 Mar 2012 10:41:00 +0200 From: Romain Bardou User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.24) Gecko/20111114 Icedove/3.1.16 MIME-Version: 1.0 To: Goswin von Brederlow CC: caml-list@inria.fr X-Ovh-Mailout: 178.32.228.4 (mo4.mail-out.ovh.net) References: <87fwcx6ejm.fsf@frosties.localnet> In-Reply-To: <87fwcx6ejm.fsf@frosties.localnet> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Ovh-Tracer-Id: 3144919916732274463 X-Ovh-Remote: 138.231.81.152 () X-Ovh-Local: 213.186.33.20 (ns0.ovh.net) X-OVH-SPAMSTATE: OK X-OVH-SPAMSCORE: 0 X-OVH-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeegtddrtdefucetggdotefuucfrrhhofhhilhgvmecuqfggjfenuceurghilhhouhhtmecufedttdenucenucfhrhhomheptfhomhgrihhnuceurghrughouhcuoegsrghrughouheslhhsvhdrvghnshdqtggrtghhrghnrdhfrheqnecujfgurhepkfffhfgfggfvufhfjggtgfesthekrgdttdefud X-Spam-Check: DONE|U 0.5/N X-VR-SPAMSTATE: OK X-VR-SPAMSCORE: 0 X-VR-SPAMCAUSE: gggruggvucftvghtrhhoucdtuddrfeegvddrheefucetggdotefuucfrrhhofhhilhgvmecuqfggjfenuceurghilhhouhhtmecufedttdenucenucfhrhhomheptfhomhgrihhnuceurghrughouhcuoegsrghrughouheslhhsvhdrvghnshdqtggrtghhrghnrdhfrheqnecujfgurhepkfffhfgfggfvufhfjggtgfesthekrgdttdefud X-Validation-by: bardou@lsv.ens-cachan.fr Subject: Re: [Caml-list] Wish: mutable variant types, equivalence with records Le 24/03/2012 19:26, Goswin von Brederlow a écrit : > 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 = of [mutable][: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 Hello, I have been wishing for this for a long time. Mainly because it's just tedious to declare a record for each constructor. Too often do I start with constructors with a low argument count (say 1 to 3) and find that I have to add new arguments. At some point I have so many arguments that I really have to declare the record, and thus rewrite all the relevant parts of the code. I would add that it would be convenient for me to be able to name only *some* of the arguments. For instance : type t = Sum of pos: Lexing.position * t * t I would access the anonymous arguments using pattern-matching as usual, and use ".pos" as a shortcut sometimes. Unifying records and sums is great, unifying tuples at the same time seems even better to me. The OPA language (of Mlstate) does this, if I'm not mistaken. Cheers, -- Romain Bardou