caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
To: Goswin von Brederlow <goswin-v-b@web.de>
Cc: OCaML List Mailing <caml-list@inria.fr>
Subject: Re: [Caml-list] A shallow option type
Date: Mon, 7 May 2012 17:11:04 +0900	[thread overview]
Message-ID: <D350BA18-9214-47C7-8921-4D4AFD4DE356@math.nagoya-u.ac.jp> (raw)
In-Reply-To: <4A169BB4-3316-437A-9E73-FABEAEDB9D2F@math.nagoya-u.ac.jp>

Sorry for all these mails.
Looks like I don't think well when I'm sleepy...

Anyway, I think that at last I have a reasonable (much simpler) solution.
This still uses sopt_tag (i.e. lazy_tag-1), but this time the argument is
the number of "some" constructors, so there is no extra cost for marshaling.
The only values on which Sopt.some is not the identity are those with a
single argument, which is additionally represented by an integer between 0 and last.
Moreover, even if for some reason you build such a value using a real sum
type, you still have Sopt.arg (Sopt.some v) = v, the only change being a loss
of sharing (which is anyway not guaranteed by the ocaml specification).

Jacques

module Sopt : sig
 type +'a t
 val none : 'a t
 val some : 'a -> 'a t
 val is_none : 'a t -> bool
 val arg  : 'a t -> 'a
 val depth : 'a t -> int
end = struct
 type 'a t = Obj.t
 let sopt_tag = Obj.lazy_tag - 1
 let none = Obj.new_block sopt_tag 1
 let last = 255
 let area = Array.create (last+1) none
 let () =
   Obj.set_field none 0 (Obj.repr 0);
   for i = 1 to last do
     let stub = Obj.new_block sopt_tag 1 in
     Obj.set_field stub 0 (Obj.repr i);
     area.(i) <- stub
   done
 let is_none x = (x = none)
 let is_sopt x =
   Obj.is_block x && Obj.tag x = sopt_tag && Obj.size x = 1 &&
   let i = Obj.obj (Obj.field x 0) in i >= 0 && i <= last
 let depth x =
   let x = Obj.repr x in
   if is_sopt x then Obj.obj (Obj.field x 0) else -1
 let some (x : 'a) : 'a t =
   let i = depth x in
   if i < 0 then Obj.magic x else
   if i = last then invalid_arg "Sopt.some" else Obj.obj area.(i+1)
 let arg (x : 'a t) : 'a =
   let i = depth x in
   if i < 0 then Obj.magic x else
   if i = 0 then invalid_arg "Sopt.arg" else Obj.obj area.(i-1)
end



  parent reply	other threads:[~2012-05-07  8:10 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-05 13:33 Goswin von Brederlow
2012-05-05 13:50 ` Gabriel Scherer
2012-05-05 14:48 ` Andreas Rossberg
2012-05-05 15:07   ` Andreas Rossberg
2012-05-05 16:22   ` Goswin von Brederlow
2012-05-05 17:11     ` Gabriel Scherer
2012-05-06 10:12       ` Goswin von Brederlow
2012-05-06 10:20     ` Goswin von Brederlow
2012-05-06 13:01 ` Jacques Garrigue
2012-05-06 15:34   ` Goswin von Brederlow
2012-05-07  0:29     ` Jacques Garrigue
2012-05-07  1:27     ` Jacques Garrigue
2012-05-07  2:34       ` Jacques Garrigue
2012-05-07  8:11       ` Jacques Garrigue [this message]
2012-05-07 17:07         ` Goswin von Brederlow
2012-05-08  0:07           ` Jacques Garrigue

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=D350BA18-9214-47C7-8921-4D4AFD4DE356@math.nagoya-u.ac.jp \
    --to=garrigue@math.nagoya-u.ac.jp \
    --cc=caml-list@inria.fr \
    --cc=goswin-v-b@web.de \
    /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).